using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Linq;
using System.Xml;
using System.IO;
using SDMX_Structure = SDMX_ML.Framework.Structure;
using SDMX_Message = SDMX_ML.Framework.Message;
using SDMX_Common = SDMX_ML.Framework.Common;
using SDMX_ML.Framework.Interfaces;


namespace SDMX_ML.Framework.Messages
{
    /// <summary>
    /// Structure message.
    /// </summary>
    /// <para>
    /// <code lang="C#">
    /// Structure structure = Structure.Load("C:\Temp\structure.xml");
    /// </code>
    /// </para>
    public class Structure : IMessage
    {
        private List<SDMX_Structure.CodelistType> _codelists;
        private List<SDMX_Structure.ConceptType> _concepts;
        private SDMX_Structure.KeyFamiliesType _keyfamilies;
        private List<SDMX_Structure.ConceptSchemeType> _conceptSchemes;
        private List<SDMX_Common.AnnotationsType> _conceptAnnotations;
        private List<SDMX_Structure.CategorySchemeType> _categorySchemes;
        private List<SDMX_Structure.HierarchicalCodelistType> _hierarchicalcodelists;
        private SDMX_Message.HeaderType _header;
        private XDocument _xmldoc;
        private XElement _xml;
        private XNamespace _nsStructurMessage;
        private XNamespace _nsStructur;
        private XNamespace _nsMessage;
        private XNamespace _nsCommon;


        /// <summary>
        /// Empty constructor.
        /// </summary>
        public Structure()
        {
            GenerateLists();
            _nsStructur = Namespaces.GetNS("structure");
            _nsCommon = Namespaces.GetNS("common");
            _nsMessage = Namespaces.GetNS("message");
            
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="structure">Xml as string.</param>
        public Structure(string structure)
        {
            GenerateLists();

            _xml = XElement.Parse(structure);

            setNameSpace();

            setStructur();

        }

        private void GenerateLists()
        {
            _codelists = new List<SDMX_Structure.CodelistType>();
            _concepts = new List<SDMX_Structure.ConceptType>();
            _keyfamilies = new SDMX_Structure.KeyFamiliesType();
            _conceptSchemes = new List<SDMX_Structure.ConceptSchemeType>();
            _conceptAnnotations = new List<SDMX_Common.AnnotationsType>();
            _categorySchemes = new List<SDMX_Structure.CategorySchemeType>();
            _hierarchicalcodelists = new List<SDMX_Structure.HierarchicalCodelistType>();

        }

        private void setNameSpace()
        {
            _nsStructurMessage = _xml.Name.Namespace;


            //Finding the prefix used for the structure namespace
            string prefixStructure = _xml.GetPrefixOfNamespace(Namespaces.GetNS("structure"));

            if (prefixStructure != null)
            {
                //create the structure namespace used in the xml structure file
                _nsStructur = _xml.GetNamespaceOfPrefix(prefixStructure);
            }
            else
            {
                _nsStructur = _xml.GetDefaultNamespace();
            }

            //Finding the prefix used for the common namespace
            string prefixCommon = _xml.GetPrefixOfNamespace(Namespaces.GetNS("common"));
            //create the common namespace used in the xml structure file

            if (prefixCommon != null)
            {
                _nsCommon = _xml.GetNamespaceOfPrefix(prefixCommon);
            }

            //Finding the prefix used for the message namespace
            string prefixMessage = _xml.GetPrefixOfNamespace(Namespaces.GetNS("message"));

            if (prefixMessage != null)
            {
                //create the common namespace used in the xml structure file
                _nsMessage = _xml.GetNamespaceOfPrefix(prefixMessage);
            }
            else
            {
                _nsMessage = _xml.GetDefaultNamespace();
            }

            
        }

        private void setStructur()
        {
            XElement header = _xml.Element(_nsMessage + "Header");
            XElement codelists = _xml.Element(_nsMessage + "CodeLists");
            XElement keyfamilies = _xml.Element(_nsMessage + "KeyFamilies");
            XElement concepts = _xml.Element(_nsMessage + "Concepts");
            XElement categorySchemes = _xml.Element(_nsMessage + "CategorySchemes");
            XElement hierarchicalcodelists = _xml.Element(_nsMessage + "HierarchicalCodelists");

            if (header != null)
            {
                _header = new SDMX_Message.HeaderType(header);
            }

            if (hierarchicalcodelists != null)
            {
                SetHierarchicalCodelists(hierarchicalcodelists);
            }

            if (categorySchemes != null)
            {
                SetCategorySchemes(categorySchemes);
            }

            if (codelists != null)
            {
                setCodelists(codelists);
            }

            if (keyfamilies != null)
            {
                setKeyFamilies(keyfamilies);
            }

            if (concepts != null)
            {
                setConcepts(concepts);
            }

        }

        private void SetHierarchicalCodelists(XElement enHierarchicalCodelists)
        {
            IEnumerable<XElement> hierarchicalCodelists = enHierarchicalCodelists.Elements(_nsStructur + "HierarchicalCodelist");

            foreach (XElement hierarchicalCodelist in hierarchicalCodelists)
            {
                SetHierarchicalCodelist(hierarchicalCodelist);
            }
        }

        private void SetHierarchicalCodelist(XElement enHieratchicalCodelist)
        {
            SDMX_Structure.HierarchicalCodelistType hierarchicalCodelistType = null;
            SDMX_Common.IDType id = null;
            SDMX_Common.IDType agencyID = null;

            if (enHieratchicalCodelist.Element(_nsStructur + "Name") != null & 
                enHieratchicalCodelist.Attribute("id") != null & 
                enHieratchicalCodelist.Attribute("agencyID") != null)
            {
                

                if (!String.IsNullOrEmpty(enHieratchicalCodelist.Attribute("id").Value))
                {
                    id = ObjectBuilder.GetIDType(enHieratchicalCodelist.Attribute("id").Value);
                }
                else
                {
                    throw new Exception("Value in attribute id is required.");
                }

                if (!String.IsNullOrEmpty(enHieratchicalCodelist.Attribute("agencyID").Value))
                {
                    agencyID = ObjectBuilder.GetIDType(enHieratchicalCodelist.Attribute("agencyID").Value);
                }
                else
                {
                    throw new Exception("Value in attribute agencyID is required.");
                }

                if (!String.IsNullOrEmpty(enHieratchicalCodelist.Element(_nsStructur + "Name").Value))
                {
                    IEnumerable<XElement> names = enHieratchicalCodelist.Elements(_nsStructur + "Name");

                    foreach (XElement name in names)
                    {
                        if (hierarchicalCodelistType == null)
                        {
                            if (!String.IsNullOrEmpty(name.Value))
                            {
                                hierarchicalCodelistType = new SDMX_Structure.HierarchicalCodelistType(ObjectBuilder.GetTextType(name), id, agencyID);
                            }

                        }
                        else
                        {
                            if (!String.IsNullOrEmpty(name.Value))
                            {
                                hierarchicalCodelistType.Name.Add(ObjectBuilder.GetTextType(name));
                            }
                        }
                    }
                }
                else
                {
                    throw new Exception("Value in element name is required.");
                }

                
            }
            else
            {
                throw new Exception("Element Name attribute id and attribute agencyID are required in HierarchicalCodelistType.");
            }

            if (enHieratchicalCodelist.Element(_nsStructur + "Description") != null)
            {
                IEnumerable<XElement> descriptions = enHieratchicalCodelist.Elements(_nsStructur + "Description");

                foreach (XElement desc in descriptions)
                {
                    if (desc.Value != null)
                    {
                        hierarchicalCodelistType.Description.Add(ObjectBuilder.GetTextType(desc));
                    }
                }
            }

            if (enHieratchicalCodelist.Element(_nsStructur + "CodelistRef") != null)
            {
                IEnumerable<XElement> codelistRefs = enHieratchicalCodelist.Elements(_nsStructur + "CodelistRef");

                foreach (XElement codelistRef in codelistRefs)
                {
                    hierarchicalCodelistType.CodelistRef.Add(SetCodelistRef(codelistRef));
                }
            }

            if (enHieratchicalCodelist.Element(_nsStructur + "Hierarchy") != null)
            {
                IEnumerable<XElement> hierarchies = enHieratchicalCodelist.Elements(_nsStructur + "Hierarchy");

                foreach (XElement hierarchy in hierarchies)
                {
                    hierarchicalCodelistType.Hierarchy.Add(SetHierarchyType(hierarchy));
                }
            }

            if (enHieratchicalCodelist.Element(_nsStructur + "Annotations") != null)
            {
                hierarchicalCodelistType.Annotations = ObjectBuilder.GetAnnotationsType(enHieratchicalCodelist.Element(_nsStructur + "Annotations"));
            }

            if (enHieratchicalCodelist.Attribute("version") != null)
            {
                if (!String.IsNullOrEmpty(enHieratchicalCodelist.Attribute("version").Value))
                {
                    hierarchicalCodelistType.Version = enHieratchicalCodelist.Attribute("version").Value;
                }
            }

            if (enHieratchicalCodelist.Attribute("urn") != null)
            {
                if (!String.IsNullOrEmpty(enHieratchicalCodelist.Attribute("urn").Value))
                {
                    hierarchicalCodelistType.Urn = enHieratchicalCodelist.Attribute("urn").Value;
                }
            }

            if (enHieratchicalCodelist.Attribute("uri") != null)
            {
                if (!String.IsNullOrEmpty(enHieratchicalCodelist.Attribute("uri").Value))
                {
                    hierarchicalCodelistType.Uri = enHieratchicalCodelist.Attribute("uri").Value;
                }
            }

            if (enHieratchicalCodelist.Attribute("isExternalReference") != null)
            {
                if (!String.IsNullOrEmpty(enHieratchicalCodelist.Attribute("isExternalReference").Value))
                {
                    hierarchicalCodelistType.IsExternalReference = Convert.ToBoolean(enHieratchicalCodelist.Attribute("isExternalReference").Value);
                }
            }

            if (enHieratchicalCodelist.Attribute("isFinal") != null)
            {
                if (!String.IsNullOrEmpty(enHieratchicalCodelist.Attribute("isFinal").Value))
                {
                    hierarchicalCodelistType.IsFinal = Convert.ToBoolean(enHieratchicalCodelist.Attribute("isFinal").Value);
                }
            }

            if (enHieratchicalCodelist.Attribute("validFrom") != null)
            {
                if (!String.IsNullOrEmpty(enHieratchicalCodelist.Attribute("validFrom").Value))
                {
                    hierarchicalCodelistType.ValidFrom = enHieratchicalCodelist.Attribute("validFrom").Value;
                }
            }

            if (enHieratchicalCodelist.Attribute("validTo") != null)
            {
                if (!String.IsNullOrEmpty(enHieratchicalCodelist.Attribute("validTo").Value))
                {
                    hierarchicalCodelistType.ValidTo = enHieratchicalCodelist.Attribute("validTo").Value;
                }
            }

            _hierarchicalcodelists.Add(hierarchicalCodelistType);

        }

        private SDMX_Structure.CodelistRefType SetCodelistRef(XElement codelistRef)
        {
            SDMX_Structure.CodelistRefType codelistRefType = new SDMX_Structure.CodelistRefType();

            if (codelistRef.Element(_nsStructur + "URN") != null)
            {
                if (!String.IsNullOrEmpty(codelistRef.Element(_nsStructur + "URN").Value))
                {
                    codelistRefType.Urn = codelistRef.Element(_nsStructur + "URN").Value;
                }
            }

            if (codelistRef.Element(_nsStructur + "AgencyID") != null)
            {
                if (!String.IsNullOrEmpty(codelistRef.Element(_nsStructur + "AgencyID").Value))
                {
                    codelistRefType.AgencyID = ObjectBuilder.GetIDType(codelistRef.Element(_nsStructur + "AgencyID").Value);
                }
            }

            if (codelistRef.Element(_nsStructur + "CodelistID") != null)
            {
                if (!String.IsNullOrEmpty(codelistRef.Element(_nsStructur + "CodelistID").Value))
                {
                    codelistRefType.CodelistID = ObjectBuilder.GetIDType(codelistRef.Element(_nsStructur + "CodelistID").Value);
                }
            }

            if (codelistRef.Element(_nsStructur + "Version") != null)
            {
                if (!String.IsNullOrEmpty(codelistRef.Element(_nsStructur + "Version").Value))
                {
                    codelistRefType.Version = codelistRef.Element(_nsStructur + "Version").Value;
                }
            }

            if (codelistRef.Element(_nsStructur + "Alias") != null)
            {
                if (!String.IsNullOrEmpty(codelistRef.Element(_nsStructur + "Alias").Value))
                {
                    codelistRefType.Alias = ObjectBuilder.GetIDType(codelistRef.Element(_nsStructur + "Alias").Value);
                }
            }

            return codelistRefType;
        }

        private SDMX_Structure.HierarchyType SetHierarchyType(XElement hierarchy)
        {
            SDMX_Structure.HierarchyType hierarchyType = null;
            SDMX_Common.IDType id = null;

            if (hierarchy.Attribute("id") != null & hierarchy.Element(_nsStructur + "Name") != null)
            {
                if (!String.IsNullOrEmpty(hierarchy.Attribute("id").Value))
                {
                    id = ObjectBuilder.GetIDType(hierarchy.Attribute("id").Value);
                }
                else
                {
                    throw new Exception("Value in attribute id in HierarchyTYpe is required.");
                }

                if (!String.IsNullOrEmpty(hierarchy.Element(_nsStructur + "Name").Value))
                {
                    hierarchyType = new SDMX_Structure.HierarchyType(ObjectBuilder.GetTextType(hierarchy.Element(_nsStructur + "Name")), id);
                }
                else
                {
                    throw new Exception("Value in element Name in HierarchyType is required.");
                }
            }
            else
            {
                throw new Exception("Element Name and attribute id are required in HierarchyType.");
            }

            if (hierarchy.Element(_nsStructur + "Description") != null)
            {
                IEnumerable<XElement> descriptions = hierarchy.Elements(_nsStructur + "Description");

                foreach (XElement desc in descriptions)
                {
                    if (!String.IsNullOrEmpty(desc.Value))
                    {
                        hierarchyType.Description.Add(ObjectBuilder.GetTextType(desc));
                    }
                }
            }

            if (hierarchy.Element(_nsStructur + "CodeRef") != null)
            {
                IEnumerable<XElement> codeRefs = hierarchy.Elements(_nsStructur + "CodeRef");

                foreach (XElement codeRef in codeRefs)
                {
                    hierarchyType.CodeRef.Add(SetCodeRefType(codeRef));
                }
            }

            if (hierarchy.Element(_nsStructur + "Level") != null)
            {
                IEnumerable<XElement> levels = hierarchy.Elements(_nsStructur + "Level");

                foreach (XElement level in levels)
                {
                    hierarchyType.Level.Add(SetLevelType(level));
                }
            }

            if (hierarchy.Element(_nsStructur + "Annotations") != null)
            {
                hierarchyType.Annotations = ObjectBuilder.GetAnnotationsType(hierarchy.Element(_nsStructur + "Annotations"));
            }

            if (hierarchy.Attribute("urn") != null)
            {
                if (!String.IsNullOrEmpty(hierarchy.Attribute("urn").Value))
                {
                    hierarchyType.Urn = hierarchy.Attribute("urn").Value;
                }
            }

            if (hierarchy.Attribute("version") != null)
            {
                if (!String.IsNullOrEmpty(hierarchy.Attribute("version").Value))
                {
                    hierarchyType.Version = hierarchy.Attribute("version").Value;
                }
            }

            if (hierarchy.Attribute("isFinal") != null)
            {
                if (!String.IsNullOrEmpty(hierarchy.Attribute("isFinal").Value))
                {
                    hierarchyType.IsFinal = Convert.ToBoolean(hierarchy.Attribute("isFinal").Value);
                }
            }

            if (hierarchy.Attribute("validFrom") != null)
            {
                if (!String.IsNullOrEmpty(hierarchy.Attribute("validFrom").Value))
                {
                    hierarchyType.ValidFrom = hierarchy.Attribute("validFrom").Value;
                }
            }

            if (hierarchy.Attribute("validTo") != null)
            {
                if (!String.IsNullOrEmpty(hierarchy.Attribute("validTo").Value))
                {
                    hierarchyType.ValidTo = hierarchy.Attribute("validTo").Value;
                }
            }

            return hierarchyType;
        }

        private SDMX_Structure.LevelType SetLevelType(XElement level)
        {
            SDMX_Structure.LevelType levelType = null;
            SDMX_Common.IDType id = null;
            int? order = null;


            if (level.Element(_nsStructur + "Name") != null & level.Element(_nsStructur + "Order") != null &
                level.Attribute("id") != null)
            {
                if (level.Attribute("id").Value != null)
                {
                    id = ObjectBuilder.GetIDType(level.Attribute("id").Value);
                }
                else
                {
                    throw new Exception("Value in attribute id in LevelType is required.");
                }

                if(!String.IsNullOrEmpty(level.Element(_nsStructur + "Order").Value))
                {
                    int test;
                    if (Int32.TryParse(level.Element(_nsStructur + "Order").Value, out test))
                    {
                        order = test;
                    }
                    else
                    {
                        throw new Exception("Value in attribute Order is not an integer.");
                    }
                }
                else
                {
                    throw new Exception("Value in element Order in LevelType is required.");
                }

                IEnumerable<XElement> names = level.Elements(_nsStructur + "Name");

                foreach (XElement name in names)
                {
                    if (!String.IsNullOrEmpty(name.Value))
                    {
                        if (levelType == null)
                        {
                            levelType = new SDMX_Structure.LevelType(ObjectBuilder.GetTextType(name), order, id);
                        }
                        else
                        {
                            levelType.Name.Add(ObjectBuilder.GetTextType(name));
                        }
                    }
                    else
                    {
                        throw new Exception("Value in element Name is required.");
                    }

                }
            }

            if (level.Element(_nsStructur + "Description") != null)
            {
                IEnumerable<XElement> descriptions = level.Elements(_nsStructur + "Description");

                foreach (XElement desc in descriptions)
                {
                    if (!String.IsNullOrEmpty(desc.Value))
                    {
                        levelType.Description.Add(ObjectBuilder.GetTextType(desc));
                    }
                }
            }

            if (level.Element(_nsStructur + "CodingType") != null)
            {
                if(!String.IsNullOrEmpty(level.Element(_nsStructur + "CodingType").Value))
                {
                    levelType.CodingType = ObjectBuilder.GetTextFormatType(level.Element(_nsStructur + "CodingType"));
                }
            }

            if (level.Element(_nsStructur + "Annotations") != null)
            {
                levelType.Annotations = ObjectBuilder.GetAnnotationsType(level.Element(_nsStructur + "Annotations"));
            }

            if (level.Attribute("urn") != null)
            {
                if(!String.IsNullOrEmpty(level.Attribute("urn").Value))
                {
                    levelType.Urn = level.Attribute("urn").Value;
                }
            }

            return levelType;

        }

        private SDMX_Structure.CodeRefType SetCodeRefType(XElement codeRef)
        {
            SDMX_Structure.CodeRefType codeRefType = new SDMX_Structure.CodeRefType();

            if (codeRef.Element(_nsStructur + "URN") != null)
            {
                if (!String.IsNullOrEmpty(codeRef.Element(_nsStructur + "URN").Value))
                {
                    codeRefType.Urn = codeRef.Element(_nsStructur + "URN").Value;
                }
            }

            if (codeRef.Element(_nsStructur + "CodelistAliasRef") != null)
            {
                if (!String.IsNullOrEmpty(codeRef.Element(_nsStructur + "CodelistAliasRef").Value))
                {
                    codeRefType.CodelistAliasRef = ObjectBuilder.GetIDType(codeRef.Element(_nsStructur + "CodelistAliasRef").Value);
                }
            }

            if (codeRef.Element(_nsStructur + "CodeID") != null)
            {
                if (!String.IsNullOrEmpty(codeRef.Element(_nsStructur + "CodeID").Value))
                {
                    codeRefType.CodeID = ObjectBuilder.GetIDType(codeRef.Element(_nsStructur + "CodeID").Value);
                }
            }

            if (codeRef.Element(_nsStructur + "CodeRef") != null)
            {
                IEnumerable<XElement> codeRefs = codeRef.Elements(_nsStructur + "CodeRef");

                foreach (XElement cRef in codeRefs)
                {
                    codeRefType.CodeRefType1.Add(SetCodeRefType(cRef));
                }
            }

            if (codeRef.Element(_nsStructur + "LevelRef") != null)
            {
                if (!String.IsNullOrEmpty(codeRef.Element(_nsStructur + "LevelRef").Value))
                {
                    codeRefType.CodeID = ObjectBuilder.GetIDType(codeRef.Element(_nsStructur + "LevelRef").Value);
                }
            }

            if (codeRef.Element(_nsStructur + "NodeAliasID") != null)
            {
                if (!String.IsNullOrEmpty(codeRef.Element(_nsStructur + "NodeAliasID").Value))
                {
                    codeRefType.NodeAliasID = codeRef.Element(_nsStructur + "NodeAliasID").Value;
                }
            }

            if (codeRef.Element(_nsStructur + "Version") != null)
            {
                if (!String.IsNullOrEmpty(codeRef.Element(_nsStructur + "Version").Value))
                {
                    codeRefType.Version = codeRef.Element(_nsStructur + "Version").Value;
                }
            }


            if (codeRef.Element(_nsStructur + "ValidFrom") != null)
            {
                if (!String.IsNullOrEmpty(codeRef.Element(_nsStructur + "ValidFrom").Value))
                {
                    codeRefType.ValidFrom = codeRef.Element(_nsStructur + "ValidFrom").Value;
                }
            }

            if (codeRef.Element(_nsStructur + "ValidTo") != null)
            {
                if (!String.IsNullOrEmpty(codeRef.Element(_nsStructur + "ValidTo").Value))
                {
                    codeRefType.ValidTo = codeRef.Element(_nsStructur + "ValidTo").Value;
                }
            }

            return codeRefType;
        }

        private void SetCategorySchemes(XElement enCategorySchemes)
        {
            
            IEnumerable<XElement> categorySchemes = enCategorySchemes.Elements(_nsStructur + "CategoryScheme");

            foreach(XElement categoryScheme in categorySchemes)
            {
                SDMX_Structure.CategorySchemeType categorySchemeType = null;

                if (categoryScheme.Element(_nsStructur + "Name") != null & categoryScheme.Attribute("id") != null &
                    categoryScheme.Attribute("agencyID") != null)
                {
                    SDMX_Common.IDType id = null;
                    SDMX_Common.IDType agencyID = null;

                    if (categoryScheme.Attribute("id").Value != null)
                    {
                        id = ObjectBuilder.GetIDType(categoryScheme.Attribute("id").Value);
                    }
                    else
                    {
                        throw new Exception("Value in attribute id in CategoryScheme is required.");
                    }

                    if (categoryScheme.Attribute("agencyID").Value != null)
                    {
                        agencyID = ObjectBuilder.GetIDType(categoryScheme.Attribute("agencyID").Value);
                    }
                    else
                    {
                        throw new Exception("Value in attribute agencyID in CategoryScheme is required.");
                    }

                    IEnumerable<XElement> names = categoryScheme.Elements(_nsStructur + "Name");

                    foreach (XElement name in names)
                    {
                        if(categorySchemeType == null)
                        {
                            categorySchemeType = new SDMX_Structure.CategorySchemeType(ObjectBuilder.GetTextType(name), id, agencyID);
                        }
                        else
                        {
                            categorySchemeType.Name.Add(ObjectBuilder.GetTextType(name));
                        }
                    }
                }
                else
                {
                    throw new Exception("Element Name and attributes id and agencyID are required.");
                }

                if (categoryScheme.Element(_nsStructur + "Description") != null)
                {
                    IEnumerable<XElement> descriptions = categoryScheme.Elements(_nsStructur + "Description");

                    foreach (XElement desc in descriptions)
                    {
                        categorySchemeType.Name.Add(ObjectBuilder.GetTextType(desc));
                    }
                }

                if (categoryScheme.Element(_nsStructur + "Category") != null)
                {
                    IEnumerable<XElement> categories = categoryScheme.Elements(_nsStructur + "Category");

                    foreach (XElement category in categories)
                    {
                        categorySchemeType.Category.Add(SetCategoryType(category));
                    }
                }

                if (categoryScheme.Element(_nsStructur + "Annotations") != null)
                {
                    categorySchemeType.Annotations = ObjectBuilder.GetAnnotationsType(categoryScheme.Element(_nsStructur + "Annotations"));
                }

                if (categoryScheme.Attribute("version") != null)
                {
                    if (!String.IsNullOrEmpty(categoryScheme.Attribute("version").Value))
                    {
                        categorySchemeType.Version = categoryScheme.Attribute("version").Value;
                    }
                }

                if (categoryScheme.Attribute("urn") != null)
                {
                    if (!String.IsNullOrEmpty(categoryScheme.Attribute("urn").Value))
                    {
                        categorySchemeType.URN = categoryScheme.Attribute("urn").Value;
                    }
                }

                if (categoryScheme.Attribute("uri") != null)
                {
                    if (!String.IsNullOrEmpty(categoryScheme.Attribute("uri").Value))
                    {
                        categorySchemeType.URI = categoryScheme.Attribute("uri").Value;
                    }
                }

                if (categoryScheme.Attribute("isExternalReference") != null)
                {
                    if (!String.IsNullOrEmpty(categoryScheme.Attribute("isExternalReference").Value))
                    {
                        categorySchemeType.IsExternalReference = Convert.ToBoolean(categoryScheme.Attribute("isExternalReference").Value.ToLower());
                    }
                }

                if (categoryScheme.Attribute("isFinal") != null)
                {
                    if (!String.IsNullOrEmpty(categoryScheme.Attribute("isFinal").Value))
                    {
                        categorySchemeType.IsFinal = Convert.ToBoolean(categoryScheme.Attribute("isFinal").Value.ToLower());
                    }
                }

                if (categoryScheme.Attribute("validFrom") != null)
                {
                    if (!String.IsNullOrEmpty(categoryScheme.Attribute("validFrom").Value))
                    {
                        categorySchemeType.ValidFrom = categoryScheme.Attribute("validFrom").Value;
                    }
                }

                if (categoryScheme.Attribute("validTo") != null)
                {
                    if (!String.IsNullOrEmpty(categoryScheme.Attribute("validTo").Value))
                    {
                        categorySchemeType.ValidTo = categoryScheme.Attribute("validTo").Value;
                    }
                }


                _categorySchemes.Add(categorySchemeType);
            }
            
        }

        private SDMX_Structure.CategoryType SetCategoryType(XElement enCategory)
        {
            SDMX_Structure.CategoryType categoryType = null;

            if (enCategory.Element(_nsStructur + "Name") != null & enCategory.Attribute("id") != null)
            {
                SDMX_Common.IDType id = null;

                if (enCategory.Attribute("id").Value != null)
                {
                    id = new SDMX_Common.IDType(enCategory.Attribute("id").Value);
                }
                else
                {
                    throw new Exception("Value in attribute id is required in CategoryType.");
                }

                IEnumerable<XElement> names = enCategory.Elements(_nsStructur + "Name");

                foreach (XElement name in names)
                {
                    if (categoryType == null)
                    {
                        categoryType = new SDMX_Structure.CategoryType(ObjectBuilder.GetTextType(name), id);
                    }
                    else
                    {
                        categoryType.Name.Add(ObjectBuilder.GetTextType(name));
                    }
                    
                }
            }

            if (enCategory.Attribute("version") != null)
            {
                if (!String.IsNullOrEmpty(enCategory.Attribute("version").Value))
                {
                    categoryType.Version = enCategory.Attribute("version").Value;
                }
            }

            if (enCategory.Attribute("urn") != null)
            {
                if (!String.IsNullOrEmpty(enCategory.Attribute("urn").Value))
                {
                    categoryType.URN = enCategory.Attribute("urn").Value;
                }
            }

            if (enCategory.Attribute("uri") != null)
            {
                if (!String.IsNullOrEmpty(enCategory.Attribute("uri").Value))
                {
                    categoryType.URI = enCategory.Attribute("uri").Value;
                }
            }

            if (enCategory.Attribute("isExternalReference") != null)
            {
                if (!String.IsNullOrEmpty(enCategory.Attribute("isExternalReference").Value))
                {
                    categoryType.IsExternalReference = Convert.ToBoolean(enCategory.Attribute("isExternalReference").Value.ToLower());
                }
            }

            if (enCategory.Element(_nsStructur + "Description") != null)
            {
                IEnumerable<XElement> descriptions = enCategory.Elements(_nsStructur + "Description");

                foreach (XElement desc in descriptions)
                {
                    categoryType.Name.Add(ObjectBuilder.GetTextType(desc));
                }
            }

            if (enCategory.Element(_nsStructur + "DataflowRef") != null)
            {
                IEnumerable<XElement> dataFlowRefs = enCategory.Elements(_nsStructur + "DataflowRef");

                foreach (XElement dataFlowRef in dataFlowRefs)
                {
                    categoryType.DataFlowRef.Add(SetDataflowRefType(dataFlowRef));
                }
            }

            if (enCategory.Element(_nsStructur + "MetadataflowRef") != null)
            {
                IEnumerable<XElement> metaDataFlowRefs = enCategory.Elements(_nsStructur + "MetadataflowRef");

                foreach (XElement metaDataFlowRef in metaDataFlowRefs)
                {
                    categoryType.MetadataFlowRef.Add(SetMetadataflowRefType(metaDataFlowRef));
                }
            }

            if (enCategory.Element(_nsStructur + "Category") != null)
            {
                IEnumerable<XElement> categories = enCategory.Elements(_nsStructur + "Category");

                foreach (XElement category in categories)
                {
                    categoryType.Category.Add(SetCategoryType(category));
                }
            }

            if (enCategory.Element(_nsStructur + "Annotations") != null)
            {
                categoryType.Annotations = ObjectBuilder.GetAnnotationsType(enCategory.Element(_nsStructur + "Annotations"));
            }

            return categoryType;
        }

        private SDMX_Structure.DataflowRefType SetDataflowRefType(XElement enDataflowRefType)
        {
            SDMX_Structure.DataflowRefType dataflowRefType = new SDMX_Structure.DataflowRefType();

            if (enDataflowRefType.Element(_nsStructur + "URN") != null)
            {
                IEnumerable<XElement> urns = enDataflowRefType.Elements(_nsStructur + "URN");

                foreach (XElement urn in urns)
                {
                    if (!String.IsNullOrEmpty(urn.Value))
                    {
                        dataflowRefType.URN.Add(urn.Value);
                    }
                }
            }

            if (enDataflowRefType.Element(_nsStructur + "AgencyID") != null)
            {
                IEnumerable<XElement> agencyIDs = enDataflowRefType.Elements(_nsStructur + "AgencyID");

                foreach (XElement agencyID in agencyIDs)
                {
                    if (!String.IsNullOrEmpty(agencyID.Value))
                    {
                        dataflowRefType.AgencyID.Add(ObjectBuilder.GetIDType(agencyID.Value));
                    }
                }
            }

            if (enDataflowRefType.Element(_nsStructur + "DataflowID") != null)
            {
                IEnumerable<XElement> dataflowIDs = enDataflowRefType.Elements(_nsStructur + "DataflowID");

                foreach (XElement dataflowID in dataflowIDs)
                {
                    if (!String.IsNullOrEmpty(dataflowID.Value))
                    {
                        dataflowRefType.DataFlowID.Add(ObjectBuilder.GetIDType(dataflowID.Value));
                    }
                }
            }

            if (enDataflowRefType.Element(_nsStructur + "Version") != null)
            {
                IEnumerable<XElement> versions = enDataflowRefType.Elements(_nsStructur + "Version");

                foreach (XElement version in versions)
                {
                    if (!String.IsNullOrEmpty(version.Value))
                    {
                        dataflowRefType.URN.Add(version.Value);
                    }
                }
            }

            return dataflowRefType;
        }

        private SDMX_Structure.MetadataflowRefType SetMetadataflowRefType(XElement enMetadataflowRefType)
        {
            SDMX_Structure.MetadataflowRefType metadataFlowRefType = new SDMX_Structure.MetadataflowRefType();

            if (enMetadataflowRefType.Element(_nsStructur + "URN") != null)
            {
                IEnumerable<XElement> urns = enMetadataflowRefType.Elements(_nsStructur + "URN");

                foreach (XElement urn in urns)
                {
                    if (!String.IsNullOrEmpty(urn.Value))
                    {
                        metadataFlowRefType.URN.Add(urn.Value);
                    }
                }
            }

            if (enMetadataflowRefType.Element(_nsStructur + "AgencyID") != null)
            {
                IEnumerable<XElement> agencyIDs = enMetadataflowRefType.Elements(_nsStructur + "AgencyID");

                foreach (XElement agencyID in agencyIDs)
                {
                    if (!String.IsNullOrEmpty(agencyID.Value))
                    {
                        metadataFlowRefType.AgencyID.Add(ObjectBuilder.GetIDType(agencyID.Value));
                    }
                }
            }

            if (enMetadataflowRefType.Element(_nsStructur + "DataflowID") != null)
            {
                IEnumerable<XElement> metaDataflowIDs = enMetadataflowRefType.Elements(_nsStructur + "MetadataflowID");

                foreach (XElement metaDataflowID in metaDataflowIDs)
                {
                    if (!String.IsNullOrEmpty(metaDataflowID.Value))
                    {
                        metadataFlowRefType.MetadataFlowID.Add(ObjectBuilder.GetIDType(metaDataflowID.Value));
                    }
                }
            }

            if (enMetadataflowRefType.Element(_nsStructur + "Version") != null)
            {
                IEnumerable<XElement> versions = enMetadataflowRefType.Elements(_nsStructur + "Version");

                foreach (XElement version in versions)
                {
                    if (!String.IsNullOrEmpty(version.Value))
                    {
                        metadataFlowRefType.URN.Add(version.Value);
                    }
                }
            }

            return metadataFlowRefType;
        }

        private void setCodelists(XElement enCodeLists)
        {
            
            IEnumerable<XElement> codeLists = enCodeLists.Elements(_nsStructur + "CodeList");

            foreach(XElement codeList in codeLists)
            {
                SDMX_Structure.CodelistType codelistType = null;
                string id = string.Empty;
                string agencyid = string.Empty;

                if (codeList != null)
                {
                    if (codeList.Attribute("id").Value != null)
                    {
                        id = codeList.Attribute("id").Value;
                    }
                    else
                    {
                        throw new Exception("Attribute id is missing for codelist");
                    }

                    if (codeList.Attribute("agencyID").Value != null)
                    {
                        agencyid = codeList.Attribute("agencyID").Value;
                    }
                    else
                    {
                        throw new Exception("Attribute agencyID is missing.");
                    }

                    codelistType = new SDMX_Structure.CodelistType(id, agencyid);

                    if (codeList.Attribute("version") != null)
                    {
                        if (codeList.Attribute("version").Value != null)
                        {
                            codelistType.Version = codeList.Attribute("version").Value;
                        }
                    }

                    if (codeList.Attribute("uri") != null)
                    {
                        if (codeList.Attribute("uri").Value != null)
                        {
                            codelistType.Uri = codeList.Attribute("uri").Value;
                        }
                    }

                    if (codeList.Attribute("urn") != null)
                    {
                        if (codeList.Attribute("urn").Value != null)
                        {
                            codelistType.Urn = codeList.Attribute("urn").Value;
                        }
                    }

                    if (codeList.Attribute("isExternalReference") != null)
                    {
                        if (codeList.Attribute("isExternalReference").Value != null)
                        {
                            codelistType.IsExternalReference = Convert.ToBoolean(codeList.Attribute("isExternalReference").Value);
                        }
                    }

                    if (codeList.Attribute("isFinal") != null)
                    {
                        if (codeList.Attribute("isFinal").Value != null)
                        {
                            codelistType.IsFinal = Convert.ToBoolean(codeList.Attribute("isFinal").Value);
                        }
                    }

                    if (codeList.Attribute("validFrom") != null)
                    {
                        if (codeList.Attribute("validFrom").Value != null)
                        {
                            SDMX_Common.TimePeriodType timePeriod = new SDMX_Common.TimePeriodType();
                            timePeriod.TimePeriod = codeList.Attribute("validFrom").Value;
                            codelistType.ValidFrom = timePeriod;
                        }
                    }

                    if (codeList.Attribute("validTo") != null)
                    {
                        if (codeList.Attribute("validTo").Value != null)
                        {
                            SDMX_Common.TimePeriodType timePeriod = new SDMX_Common.TimePeriodType();
                            timePeriod.TimePeriod = codeList.Attribute("validTo").Value;
                            codelistType.ValidTo = timePeriod;
                        }
                    }

                    IEnumerable<XElement> names = codeList.Elements(_nsStructur + "Name");

                    if (names != null)
                    {
                        foreach (XElement name in names)
                        {
                            codelistType.Name.Add(ObjectBuilder.GetTextType(name));
                        }
                    }
                    else
                    {
                        throw new Exception("At least one name should be added to the codelist.");
                    }

                    IEnumerable<XElement> descriptions = codeList.Elements(_nsStructur + "Description");

                    if (descriptions != null)
                    {
                        foreach (XElement description in descriptions)
                        {
                            codelistType.Description.Add(ObjectBuilder.GetTextType(description));
                        }
                    }

                    foreach (XElement cv in codeList.Elements())
                    {
                        if (cv.Name == _nsStructur + "Code")
                        {
                            
                            SDMX_Common.IDType codeValue = new SDMX_Common.IDType();

                            if (cv.Attribute("value").Value != null)
                            {
                                codeValue.Value = cv.Attribute("value").Value;
                            }

                            SDMX_Structure.CodeType c = new SDMX_Structure.CodeType(codeValue);

                            IEnumerable<XElement> enDescriptions = cv.Elements(_nsStructur + "Description");

                            if (enDescriptions != null)
                            {
                                foreach (XElement desc in enDescriptions)
                                {
                                    c.Description.Add(ObjectBuilder.GetTextType(desc));
                                }
                            }

                            if (cv.Element(_nsStructur + "Annotations") != null)
                            {
                                c.Annotations = ObjectBuilder.GetAnnotationsType(cv.Element(_nsStructur + "Annotations"));
                            }

                            codelistType.Codevalues.Add(c);
                        }

                    }

                    if (codeList.Element(_nsStructur + "Annotations") != null)
                    {
                        codelistType.Annotations = ObjectBuilder.GetAnnotationsType(codeList.Element(_nsStructur + "Annotations"));
                    }

                    _codelists.Add(codelistType);
                }
            }
        }

        private void setCodeValues(XElement codelist)
        {

        }

        /// <summary>
        /// Creating concept objects from Xml elemnts
        /// </summary>
        /// <param name="concept"></param>
        private void setConcepts(XElement concept)
        {
            IEnumerable<XElement> concepts = concept.Elements(_nsStructur + "Concept");

            foreach(XElement c in concepts)
            {
                SDMX_Structure.ConceptType conceptType = GetConcept(c);

                //SetNameElement(c, ref conceptType);
                //SetDescriptionElement(c, ref conceptType);
                //SetTextFormatElement(c, ref conceptType);
                //SetAnnotationsElement(c, ref conceptType);

                _concepts.Add(conceptType);

            } //foreach concepts

            IEnumerable<XElement> conceptSchemes = concept.Elements(_nsStructur + "ConceptScheme");

            foreach (XElement conceptScheme in conceptSchemes)
            {
                SDMX_Structure.ConceptSchemeType conceptSchemeType = new SDMX_Structure.ConceptSchemeType();

                if (conceptScheme.Attribute("id").Value != null)
                {
                    conceptSchemeType.Id = conceptScheme.Attribute("id").Value;
                }
                else
                {
                    throw new Exception("Attribute id is missing for codelist");
                }

                if (conceptScheme.Attribute("agencyID").Value != null)
                {
                    conceptSchemeType.AgencyID = conceptScheme.Attribute("agencyID").Value;
                }
                else
                {
                    throw new Exception("Attribute agencyID is missing.");
                }

                if (conceptScheme.Attribute("version") != null)
                {
                    if (conceptScheme.Attribute("version").Value != null)
                    {
                        conceptSchemeType.Version = conceptScheme.Attribute("version").Value;
                    }
                }

                if (conceptScheme.Attribute("uri") != null)
                {
                    if (conceptScheme.Attribute("uri").Value != null)
                    {
                        conceptSchemeType.Uri = conceptScheme.Attribute("uri").Value;
                    }
                }

                if (conceptScheme.Attribute("urn") != null)
                {
                    if (conceptScheme.Attribute("urn").Value != null)
                    {
                        conceptSchemeType.Urn = conceptScheme.Attribute("urn").Value;
                    }
                }

                if (conceptScheme.Attribute("isExternalReference") != null)
                {
                    if (conceptScheme.Attribute("isExternalReference").Value != null)
                    {
                        conceptSchemeType.IsExternalReference = Convert.ToBoolean(conceptScheme.Attribute("isExternalReference").Value);
                    }
                }

                if (conceptScheme.Attribute("isFinal") != null)
                {
                    if (conceptScheme.Attribute("isFinal").Value != null)
                    {
                        conceptSchemeType.IsFinal = Convert.ToBoolean(conceptScheme.Attribute("isFinal").Value);
                    }
                }

                if (conceptScheme.Attribute("validFrom") != null)
                {
                    if (conceptScheme.Attribute("validFrom").Value != null)
                    {
                        SDMX_Common.TimePeriodType timePeriod = new SDMX_Common.TimePeriodType();
                        timePeriod.TimePeriod = conceptScheme.Attribute("validFrom").Value;
                        conceptSchemeType.ValidFrom = timePeriod;
                    }
                }

                if (conceptScheme.Attribute("validTo") != null)
                {
                    if (conceptScheme.Attribute("validTo").Value != null)
                    {
                        SDMX_Common.TimePeriodType timePeriod = new SDMX_Common.TimePeriodType();
                        timePeriod.TimePeriod = conceptScheme.Attribute("validTo").Value;
                        conceptSchemeType.ValidTo = timePeriod;
                    }
                }

                IEnumerable<XElement> names = conceptScheme.Elements(_nsStructur + "Name");

                if (names != null)
                {
                    foreach (XElement enName in names)
                    {
                        SDMX_Common.TextType name = ObjectBuilder.GetTextType(enName);

                        conceptSchemeType.Name.Add(name);
                    }
                }

                IEnumerable<XElement> descriptions = conceptScheme.Elements(_nsStructur + "Description");

                if (descriptions != null)
                {
                    foreach (XElement description in descriptions)
                    {
                        SDMX_Common.TextType textType = ObjectBuilder.GetTextType(description);

                        conceptSchemeType.Description.Add(textType);
                    }
                }

                IEnumerable<XElement> conceptSchemesConcepts = conceptScheme.Elements(_nsStructur + "Concept");

                foreach (XElement conceptSchemeConcept in conceptSchemesConcepts)
                {
                    SDMX_Structure.ConceptType conceptType = GetConcept(conceptSchemeConcept);
                    SetNameElement(conceptSchemeConcept, ref conceptType);
                    conceptSchemeType.Concept.Add(conceptType);
                }

                if (conceptScheme.Element(_nsStructur + "Annotations") != null)
                {
                    conceptSchemeType.Annotations = ObjectBuilder.GetAnnotationsType(conceptScheme.Element(_nsStructur + "Annotations"));
                }

                _conceptSchemes.Add(conceptSchemeType);
            }

            if (concept.Elements(_nsStructur + "Annotations") != null)
            {
                _conceptAnnotations = ObjectBuilder.GetAnnotations(concept, _nsCommon);
            }
        }

        private SDMX_Structure.ConceptType GetConcept(XElement concept)
        {
            SDMX_Structure.ConceptType conceptType = null;
            SDMX_Common.IDType id = null;

            if (concept.Attribute("id") != null & concept.Element(_nsStructur + "Name") != null)
            {
                if (!String.IsNullOrEmpty(concept.Attribute("id").Value))
                {
                    id = new SDMX_Common.IDType();
                    id.Value = concept.Attribute("id").Value;
                }
                else
                {
                    throw new Exception("Value in attribute id in ConceptType is required.");
                }

                IEnumerable<XElement> names = concept.Elements(_nsStructur + "Name");

                if (names != null)
                {
                    foreach (XElement enName in names)
                    {
                        if (!String.IsNullOrEmpty(enName.Value))
                        {
                            if (conceptType != null)
                            {
                                conceptType.Name.Add(ObjectBuilder.GetTextType(enName));
                            }
                            else
                            {
                                conceptType = new SDMX_Structure.ConceptType(ObjectBuilder.GetTextType(enName), id);
                            }
                        }
                    }
                }
            }
            else
            {
                throw new Exception("Attribute id and element Name are required in ConceptType.");
            }

           

            if (concept.Attribute("agencyID") != null)
            {
                SDMX_Common.IDType agencyID = new SDMX_Common.IDType();
                agencyID.Value = concept.Attribute("agencyID").Value;
                conceptType.AgencyID = agencyID;
            }

            if (concept.Attribute("version") != null)
            {
                conceptType.Version = concept.Attribute("version").Value;
            }

            if (concept.Attribute("uri") != null)
            {
                conceptType.Uri = concept.Attribute("uri").Value;
            }

            if (concept.Attribute("urn") != null)
            {
                conceptType.Urn = concept.Attribute("urn").Value;
            }

            if (concept.Attribute("isExternalReference") != null)
            {
                conceptType.IsExternalReference = Convert.ToBoolean(concept.Attribute("isExternalreference").Value);
            }

            if (concept.Attribute("coreReprensentation") != null)
            {
                SDMX_Common.IDType coreRep = new SDMX_Common.IDType();
                coreRep.Value = concept.Attribute("coreReprensentation").Value;
                conceptType.CoreRepresentation = coreRep;
            }

            if (concept.Attribute("coreReprensentationAgency") != null)
            {
                SDMX_Common.IDType coreRepAgency = new SDMX_Common.IDType();
                coreRepAgency.Value = concept.Attribute("coreReprensentationAgency").Value;
                conceptType.CoreReprensentationAgency = coreRepAgency;
            }

            if (concept.Attribute("parent") != null)
            {
                SDMX_Common.IDType parent = new SDMX_Common.IDType();
                parent.Value = concept.Attribute("parent").Value;
                conceptType.Parent = parent;
            }

            if (concept.Attribute("parentAgency") != null)
            {
                SDMX_Common.IDType parentAgency = new SDMX_Common.IDType();
                parentAgency.Value = concept.Attribute("parentAgency").Value;
                conceptType.ParentAgency = parentAgency;
            }

            

            IEnumerable<XElement> descriptions = concept.Elements(_nsStructur + "Description");

            if (descriptions != null)
            {
                foreach (XElement description in descriptions)
                {
                    SDMX_Common.TextType textType = ObjectBuilder.GetTextType(description);

                    conceptType.Description.Add(textType);
                }
            }

            XElement enTextFormat = concept.Element(_nsStructur + "TextFormat");

            if (enTextFormat != null)
            {
                SDMX_Structure.TextFormatType textFormat = new SDMX_Structure.TextFormatType();

                if (enTextFormat.Attribute(_nsStructur + "textType") != null)
                {
                    textFormat.Texttype = ObjectBuilder.GetTextTypeType(enTextFormat.Attribute(_nsStructur + "textType").Value);
                }

                if (enTextFormat.Attribute(_nsStructur + "isSequence") != null)
                {
                    textFormat.IsSequence = Convert.ToBoolean(enTextFormat.Attribute(_nsStructur + "isSequence").Value);
                }

                if (enTextFormat.Attribute(_nsStructur + "minLength") != null)
                {
                    textFormat.Minlength = Convert.ToInt16(enTextFormat.Attribute(_nsStructur + "minLength").Value);
                }

                if (enTextFormat.Attribute(_nsStructur + "maxLength") != null)
                {
                    textFormat.Maxlength = Convert.ToInt16(enTextFormat.Attribute(_nsStructur + "maxLength").Value);
                }

                if (enTextFormat.Attribute(_nsStructur + "startValue") != null)
                {
                    textFormat.Startvalue = Convert.ToDouble(enTextFormat.Attribute(_nsStructur + "startValue").Value);
                }

                if (enTextFormat.Attribute(_nsStructur + "endValue") != null)
                {
                    textFormat.Endvalue = Convert.ToDouble(enTextFormat.Attribute(_nsStructur + "endValue").Value);
                }

                if (enTextFormat.Attribute(_nsStructur + "interval") != null)
                {
                    textFormat.Interval = Convert.ToDouble(enTextFormat.Attribute(_nsStructur + "interval").Value);
                }

                if (enTextFormat.Attribute(_nsStructur + "timeInterval") != null)
                {
                    textFormat.Timeinterval = enTextFormat.Attribute(_nsStructur + "timeInterval").Value;
                }

                if (enTextFormat.Attribute(_nsStructur + "decimals") != null)
                {
                    textFormat.Decimals = Convert.ToInt16(enTextFormat.Attribute(_nsStructur + "decimals").Value);
                }

                if (enTextFormat.Attribute(_nsStructur + "pattern") != null)
                {
                    textFormat.Pattern = enTextFormat.Attribute(_nsStructur + "pattern").Value;
                }

                conceptType.Textformat = textFormat;
            }

            IEnumerable<XElement> annotations = concept.Elements(_nsStructur + "Annotations");

            if(concept.Elements(_nsStructur + "Annotations") != null)
            {
                ObjectBuilder.GetAnnotations(concept, _nsStructur);
            }

            return conceptType;
        }

        private void SetNameElement(XElement concept, ref SDMX_Structure.ConceptType conceptType)
        {
            IEnumerable<XElement> names = concept.Elements(_nsStructur + "Name");

            if (names != null)
            {
                foreach (XElement enName in names)
                {
                    SDMX_Common.TextType name = ObjectBuilder.GetTextType(enName);

                    conceptType.Name.Add(name);
                }
            }
        }

        private void SetDescriptionElement(XElement concept, ref SDMX_Structure.ConceptType conceptType)
        {
            IEnumerable<XElement> descriptions = concept.Elements(_nsStructur + "Description");

            if (descriptions != null)
            {
                foreach (XElement description in descriptions)
                {
                    SDMX_Common.TextType textType = ObjectBuilder.GetTextType(description);

                    conceptType.Description.Add(textType);
                }
            }
        }

        private void setKeyFamilies(XElement element)
        {
            //Get the xml element
            XElement kf = element.Element(_nsStructur + "KeyFamily");

            //Create object to contain values
            SDMX_Structure.KeyFamilyType keyfamily = null;
            SDMX_Common.IDType id = null;
            SDMX_Common.IDType agencyID = null;

            //id attribute is required
            if (kf.Attribute("id") != null)
            {
                if (kf.Attribute("id").Value != null)
                {
                    id = new SDMX_Common.IDType(kf.Attribute("id").Value);
                }
                else
                {
                    throw new Exception("Value for attribute id is missing in element KeyFamily!");
                }
            }
            else
            {
                throw new Exception("Attribute id in KeyFamily element is missing!");
            }

            if (kf.Attribute("agencyID") != null)
            {
                if (kf.Attribute("agencyID").Value != null)
                {
                    agencyID = new SDMX_Common.IDType(kf.Attribute("agencyID").Value);
                }
                else
                {
                    throw new Exception("Value for attribute agencyID is missing in element KeyFamily!");
                }
            }
            else
            {
                throw new Exception("Attribute agencyID in KeyFamily element is missing");
            }

            if (kf.Elements(_nsStructur + "Name") != null)
            {
                IEnumerable<XElement> kfNames = kf.Elements(_nsStructur + "Name");

                foreach (XElement k in kfNames)
                {
                    if (keyfamily != null)
                    {
                        keyfamily.Name.Add(ObjectBuilder.GetTextType(k));
                    }
                    else
                    {
                        keyfamily = new SDMX_Structure.KeyFamilyType(ObjectBuilder.GetTextType(k), id, agencyID);
                    }
                }
            }
            else
            {
                throw new Exception("Element Name is missing in element KeyFamily!");
            }

            if (kf.Attribute("version") != null)
            {
                if (kf.Attribute("version").Value != null)
                {
                    keyfamily.Version = kf.Attribute("version").Value;
                }
            }

            if (kf.Attribute("uri") != null)
            {
                if (kf.Attribute("uri").Value != null)
                {
                    keyfamily.Uri = kf.Attribute("uri").Value;
                }
            }

            if (kf.Attribute("urn") != null)
            {
                if (kf.Attribute("urn").Value != null)
                {
                    keyfamily.Urn = kf.Attribute("urn").Value;
                }
            }

            if (kf.Attribute("isFinal") != null)
            {
                if (kf.Attribute("isFinal").Value != null)
                {
                    keyfamily.Isfinal = Convert.ToBoolean(kf.Attribute("isFinal").Value);
                }
            }

            if (kf.Attribute("isExternalReference") != null)
            {
                if (kf.Attribute("isExternalReference").Value != null)
                {
                    keyfamily.IsExternalReference = Convert.ToBoolean(kf.Attribute("isExternalReference").Value);
                }
            }

            if (kf.Attribute("validFrom") != null)
            {
                if (kf.Attribute("validFrom").Value != null)
                {
                    keyfamily.ValidFrom = kf.Attribute("validFrom").Value;
                }
            }

            if (kf.Attribute("validTo") != null)
            {
                if (kf.Attribute("validTo").Value != null)
                {
                    keyfamily.ValidTo = kf.Attribute("validTo").Value;
                }
            }

            
            
            keyfamily.Component = GetComponents(kf);

            if (kf.Element(_nsStructur + "Annotations") != null)
            {
                keyfamily.Annotations = ObjectBuilder.GetAnnotationsType(kf.Element(_nsStructur + "Annotations"));
            }

            _keyfamilies.KeyFamily.Add(keyfamily);
        }

        private SDMX_Structure.ComponentsType GetComponents(XElement element)
        {
            SDMX_Structure.ComponentsType comp = new SDMX_Structure.ComponentsType();
            XElement Components = element.Element(_nsStructur + "Components");

            foreach(XElement dim in Components.Elements())
            {
                if(dim.Name == _nsStructur + "Dimension")
                {

                    Common.IDType conceptRef = null;

                    if (dim.Attribute("conceptRef") != null)
                    {
                        if (dim.Attribute("conceptRef").Value != null)
                        {
                            conceptRef = new SDMX_Common.IDType();
                            conceptRef.Value = dim.Attribute("conceptRef").Value;
                        }
                    }

                    SDMX_Structure.DimensionType d = new SDMX_Structure.DimensionType(conceptRef);

                    if (dim.Attribute("conceptVersion") != null)
                    {
                        if (dim.Attribute("conceptVersion").Value != null)
                        {
                            d.ConceptVersion = dim.Attribute("conceptVersion").Value;
                        }
                    }

                    if (dim.Attribute("conceptAgency") != null)
                    {
                        if (dim.Attribute("conceptAgency").Value != null)
                        {
                            Common.IDType conceptAgency = new SDMX_Common.IDType();
                            conceptAgency.Value = dim.Attribute("conceptAgency").Value;
                            d.ConceptAgency = conceptAgency;
                        }
                    }

                    if (dim.Attribute("conceptSchemeRef") != null)
                    {
                        if (dim.Attribute("conceptSchemeRef").Value != null)
                        {
                            Common.IDType conceptSchemaRef = new SDMX_Common.IDType();
                            conceptSchemaRef.Value = dim.Attribute("conceptSchemeRef").Value;
                            d.ConceptSchemeRef = conceptSchemaRef;
                        }
                    }

                    if (dim.Attribute("conceptSchemeAgency") != null)
                    {
                        if (dim.Attribute("conceptSchemeAgency").Value != null)
                        {
                            Common.IDType conceptSchemaAgency = new SDMX_Common.IDType();
                            conceptSchemaAgency.Value = dim.Attribute("conceptSchemeAgency").Value;
                            d.ConceptSchemeAgency = conceptSchemaAgency;
                        }
                    }

                    if (dim.Attribute("codelist") != null)
                    {
                        if (dim.Attribute("codelist").Value != null)
                        {
                            Common.IDType codelist = new SDMX_Common.IDType();
                            codelist.Value = dim.Attribute("codelist").Value;
                            d.Codelist = codelist;
                        }
                    }

                    if (dim.Attribute("codelistVersion") != null)
                    {
                        if (dim.Attribute("codelistVersion").Value != null)
                        {
                            d.CodeListVersion = dim.Attribute("codelistVersion").Value;
                        }
                    }

                    if (dim.Attribute("codelistAgency") != null)
                    {
                        if (dim.Attribute("codelistAgency").Value != null)
                        {
                            Common.IDType codelistAgency = new SDMX_Common.IDType();
                            codelistAgency.Value = dim.Attribute("codelistAgency").Value;
                            d.CodeListAgency = codelistAgency;
                        }
                    }

                    if (dim.Attribute("isMeasureDimension") != null)
                    {
                        if (dim.Attribute("isMeasureDimension").Value != null)
                        {
                            d.IsMeasureDimension = Convert.ToBoolean(dim.Attribute("isMeasureDimension").Value);
                        }
                    }

                    if (dim.Attribute("isFrequencyDimension") != null)
                    {
                        if (dim.Attribute("isFrequencyDimension").Value != null)
                        {
                            d.IsFrequencyDimension = Convert.ToBoolean(dim.Attribute("isFrequencyDimension").Value);
                        }
                    }

                    if (dim.Attribute("isEntityDimension") != null)
                    {
                        if (dim.Attribute("isEntityDimension").Value != null)
                        {
                            d.IsEntityDimension = Convert.ToBoolean(dim.Attribute("isEntityDimension").Value);
                        }
                    }

                    if (dim.Attribute("isCountDimension") != null)
                    {
                        if (dim.Attribute("isCountDimension").Value != null)
                        {
                            d.IsCountDimension = Convert.ToBoolean(dim.Attribute("isCountDimension").Value);
                        }
                    }

                    if (dim.Attribute("isNonObservationTimeDimension") != null)
                    {
                        if (dim.Attribute("isNonObservationTimeDimension").Value != null)
                        {
                            d.IsNonObservationTimeDimension = Convert.ToBoolean(dim.Attribute("isNonObservationTimeDimension").Value);
                        }
                    }

                    if (dim.Attribute("isIdentityDimension") != null)
                    {
                        if (dim.Attribute("isIdentityDimension").Value != null)
                        {
                            d.IsIdentityDimension = Convert.ToBoolean(dim.Attribute("isIdentityDimension").Value);
                        }
                    }

                    if (dim.Attribute("crossSectionalAttachDataSet") != null)
                    {
                        if (dim.Attribute("crossSectionalAttachDataSet").Value != null)
                        {
                            d.CrossSectionalAttachDataSet = Convert.ToBoolean(dim.Attribute("crossSectionalAttachDataSet").Value);
                        }
                    }

                    if (dim.Attribute("crossSectionalAttachGroup") != null)
                    {
                        if (dim.Attribute("crossSectionalAttachGroup").Value != null)
                        {
                            d.CrossSectionalAttachGroup = Convert.ToBoolean(dim.Attribute("crossSectionalAttachGroup").Value);
                        }
                    }

                    if (dim.Attribute("crossSectionalAttachSection") != null)
                    {
                        if (dim.Attribute("crossSectionalAttachSection").Value != null)
                        {
                            d.CrossSectionalAttachSection = Convert.ToBoolean(dim.Attribute("crossSectionalAttachSection").Value);
                        }
                    }

                    if (dim.Attribute("crossSectionalAttachObservation") != null)
                    {
                        if (dim.Attribute("crossSectionalAttachObservation").Value != null)
                        {
                            d.CrossSectionalAttachObservation = Convert.ToBoolean(dim.Attribute("crossSectionalAttachObservation").Value);
                        }
                    }

                    if (dim.Element(_nsStructur + "TextFormat") != null)
                    {
                        List<SDMX_Structure.TextFormatType> textFormatTypes = new List<SDMX_Structure.TextFormatType>();

                        foreach (XElement textFormat in dim.Elements(_nsStructur + "TextFormat"))
                        {
                            textFormatTypes.Add(ObjectBuilder.GetTextFormatType(textFormat));
                        }

                        d.TextFormat = textFormatTypes;
                    }

                    if (dim.Element(_nsStructur + "Annotations") != null)
                    {
                        d.Annotations = ObjectBuilder.GetAnnotationsType(dim.Element(_nsStructur + "Annotations"));
                    }

                    comp.Dimensions.Add(d);
                }
                if (dim.Name == _nsStructur + "TimeDimension")
                {
                    SDMX_Structure.TimeDimensionType timeDimensionType = new SDMX_Structure.TimeDimensionType(new SDMX_Common.IDType(dim.Attribute("conceptRef").Value));

                    if (dim.Attribute("conceptVersion") != null)
                    {
                        if (dim.Attribute("conceptVersion").Value != null)
                        {
                            timeDimensionType.ConceptVersion = dim.Attribute("conceptVersion").Value;
                        }
                    }

                    if (dim.Attribute("conceptAgency") != null)
                    {
                        if (dim.Attribute("conceptAgency").Value != null)
                        {
                            Common.IDType conceptAgency = new SDMX_Common.IDType();
                            conceptAgency.Value = dim.Attribute("conceptAgency").Value;
                            timeDimensionType.ConceptAgency = conceptAgency;
                        }
                    }

                    if (dim.Attribute("conceptSchemeRef") != null)
                    {
                        if (dim.Attribute("conceptSchemeRef").Value != null)
                        {
                            Common.IDType conceptSchemaRef = new SDMX_Common.IDType();
                            conceptSchemaRef.Value = dim.Attribute("conceptSchemeRef").Value;
                            timeDimensionType.ConceptSchemeRef = conceptSchemaRef;
                        }
                    }

                    if (dim.Attribute("conceptSchemeAgency") != null)
                    {
                        if (dim.Attribute("conceptSchemeAgency").Value != null)
                        {
                            Common.IDType conceptSchemaAgency = new SDMX_Common.IDType();
                            conceptSchemaAgency.Value = dim.Attribute("conceptSchemeAgency").Value;
                            timeDimensionType.ConceptSchemeAgency = conceptSchemaAgency;
                        }
                    }

                    if (dim.Attribute("codelist") != null)
                    {
                        if (dim.Attribute("codelist").Value != null)
                        {
                            Common.IDType codelist = new SDMX_Common.IDType();
                            codelist.Value = dim.Attribute("codelist").Value;
                            timeDimensionType.Codelist = codelist;
                        }
                    }

                    if (dim.Attribute("codelistVersion") != null)
                    {
                        if (dim.Attribute("codelistVersion").Value != null)
                        {
                            timeDimensionType.CodeListVersion = dim.Attribute("codelistVersion").Value;
                        }
                    }

                    if (dim.Attribute("codelistAgency") != null)
                    {
                        if (dim.Attribute("codelistAgency").Value != null)
                        {
                            Common.IDType codelistAgency = new SDMX_Common.IDType();
                            codelistAgency.Value = dim.Attribute("codelistAgency").Value;
                            timeDimensionType.Codelist = codelistAgency;
                        }
                    }

                    if (dim.Attribute("crossSectionalAttachDataSet") != null)
                    {
                        if (dim.Attribute("crossSectionalAttachDataSet").Value != null)
                        {
                            timeDimensionType.CrossSectionalAttachDataSet = Convert.ToBoolean(dim.Attribute("crossSectionalAttachDataSet").Value);
                        }
                    }

                    if (dim.Attribute("crossSectionalAttachGroup") != null)
                    {
                        if (dim.Attribute("crossSectionalAttachGroup").Value != null)
                        {
                            timeDimensionType.CrossSectionalAttachGroup = Convert.ToBoolean(dim.Attribute("crossSectionalAttachGroup").Value);
                        }
                    }

                    if (dim.Attribute("crossSectionalAttachSection") != null)
                    {
                        if (dim.Attribute("crossSectionalAttachSection").Value != null)
                        {
                            timeDimensionType.CrossSectionalAttachSection = Convert.ToBoolean(dim.Attribute("crossSectionalAttachSection").Value);
                        }
                    }

                    if (dim.Attribute("crossSectionalAttachObservation") != null)
                    {
                        if (dim.Attribute("crossSectionalAttachObservation").Value != null)
                        {
                            timeDimensionType.CrossSectionalAttachObservation = Convert.ToBoolean(dim.Attribute("crossSectionalAttachObservation").Value);
                        }
                    }

                    if (dim.Element(_nsStructur + "TextFormat") != null)
                    {
                        List<SDMX_Structure.TextFormatType> textFormatTypes = new List<SDMX_Structure.TextFormatType>();

                        foreach (XElement textFormat in dim.Elements(_nsStructur + "TextFormat"))
                        {
                            textFormatTypes.Add(ObjectBuilder.GetTextFormatType(textFormat));
                        }

                        timeDimensionType.TextFormat = textFormatTypes;
                    }

                    if (dim.Element(_nsStructur + "Annotations") != null)
                    {
                        timeDimensionType.Annotations = ObjectBuilder.GetAnnotationsType(dim.Element(_nsStructur + "Annotations"));
                    }

                    comp.Timedimension = timeDimensionType;


                }
                if (dim.Name == _nsStructur + "Group")
                {
                    SDMX_Structure.GroupType groupType = new SDMX_Structure.GroupType(new SDMX_Common.IDType(dim.Attribute("id").Value));

                    if (dim.Element(_nsStructur + "DimensionRef") != null)
                    {
                        foreach (XElement dimRef in dim.Elements(_nsStructur + "DimensionRef"))
                        {
                            if (dimRef.Value != null)
                            {
                                Common.IDType dimensionRef = new SDMX_Common.IDType();
                                dimensionRef.Value = dimRef.Value;
                                groupType.DimensionRef.Add(dimensionRef);
                            }
                        }
                    }
                    else if (dim.Element(_nsStructur + "AttachmentConstraintRef") != null)
                    {
                        if (dim.Element(_nsStructur + "AttachmentConstraintRef").Value != null)
                        {
                            Common.IDType attachmentConstraintRef = new SDMX_Common.IDType();
                            attachmentConstraintRef.Value = dim.Element("AttachmentConstraintRef").Value;
                            groupType.AttachmentConstraintRef = attachmentConstraintRef;
                        }
                    }

                    if (dim.Element(_nsStructur + "Description") != null)
                    {
                        groupType.Description.Add(ObjectBuilder.GetTextType(dim.Element(_nsStructur + "Description")));
                    }

                    if (dim.Element(_nsStructur + "Annotations") != null)
                    {
                        groupType.Annotations = ObjectBuilder.GetAnnotationsType(dim.Element(_nsStructur + "Annotations"));
                    }

                    comp.Group.Add(groupType);

                }
                if (dim.Name == _nsStructur + "PrimaryMeasure")
                {
                    SDMX_Structure.PrimaryMeasureType primaryMeasureType = new SDMX_Structure.PrimaryMeasureType(new SDMX_Common.IDType(dim.Attribute("conceptRef").Value));

                    if (dim.Attribute("conceptVersion") != null)
                    {
                        if (dim.Attribute("conceptVersion").Value != null)
                        {
                            primaryMeasureType.ConceptVersion = dim.Attribute("conceptVersion").Value;
                        }
                    }

                    if (dim.Attribute("conceptAgency") != null)
                    {
                        if (dim.Attribute("conceptAgency").Value != null)
                        {
                            Common.IDType conceptAgency = new SDMX_Common.IDType();
                            conceptAgency.Value = dim.Attribute("conceptAgency").Value;
                            primaryMeasureType.ConceptAgency = conceptAgency;
                        }
                    }

                    if (dim.Attribute("conceptSchemaRef") != null)
                    {
                        if (dim.Attribute("conceptSchemaRef").Value != null)
                        {
                            Common.IDType conceptSchemaRef = new SDMX_Common.IDType();
                            conceptSchemaRef.Value = dim.Attribute("conceptSchemaRef").Value;
                            primaryMeasureType.ConceptSchemaRef = conceptSchemaRef;
                        }
                    }

                    if (dim.Attribute("conceptSchemaAgency") != null)
                    {
                        if (dim.Attribute("conceptSchemaAgency").Value != null)
                        {
                            Common.IDType conceptSchemaAgency = new SDMX_Common.IDType();
                            conceptSchemaAgency.Value = dim.Attribute("conceptSchemaAgency").Value;
                            primaryMeasureType.ConceptSchemaAgency = conceptSchemaAgency;
                        }
                    }

                    if (dim.Attribute("codelist") != null)
                    {
                        if (dim.Attribute("codelist").Value != null)
                        {
                            Common.IDType codelist = new SDMX_Common.IDType();
                            codelist.Value = dim.Attribute("codelist").Value;
                            primaryMeasureType.Codelist = codelist;
                        }
                    }

                    if (dim.Attribute("codelistVersion") != null)
                    {
                        if (dim.Attribute("codelistVersion").Value != null)
                        {
                            primaryMeasureType.CodelistVersion = dim.Attribute("codelistVersion").Value;
                        }
                    }

                    if (dim.Attribute("codelistAgency") != null)
                    {
                        if (dim.Attribute("codelistAgency").Value != null)
                        {
                            Common.IDType codelistAgency = new SDMX_Common.IDType();
                            codelistAgency.Value = dim.Attribute("codelistAgency").Value;
                            primaryMeasureType.Codelist = codelistAgency;
                        }
                    }

                     if (dim.Element(_nsStructur + "TextFormat") != null)
                    {
                        foreach (XElement textFormat in dim.Elements(_nsStructur + "TextFormat"))
                        {
                            SDMX_Structure.TextFormatType textFormatType = new SDMX_Structure.TextFormatType();

                            primaryMeasureType.TextFormat.Add(ObjectBuilder.GetTextFormatType(textFormat));
                        }
                    }

                     if (dim.Element(_nsStructur + "Annotations") != null)
                    {
                        primaryMeasureType.Annotations = ObjectBuilder.GetAnnotationsType(dim.Element(_nsStructur + "Annotations"));
                    }

                    comp.Primarymeasure = primaryMeasureType;
                }
                if(dim.Name == _nsStructur + "CrossSectionalMeasure")
                {
                    SDMX_Structure.CrossSectionalMeasure crossSectionalMeasure = 
                        new SDMX_Structure.CrossSectionalMeasure(new SDMX_Common.IDType(dim.Attribute("conceptRef").Value),
                            new SDMX_Common.IDType(dim.Attribute("code").Value), new SDMX_Common.IDType(dim.Attribute("measureDimension").Value));

                    if (dim.Attribute("conceptVersion") != null)
                    {
                        if (dim.Attribute("conceptVersion").Value != null)
                        {
                            crossSectionalMeasure.ConceptVersion = dim.Attribute("conceptVersion").Value;
                        }
                    }

                    if (dim.Attribute("conceptAgency") != null)
                    {
                        if (dim.Attribute("conceptAgency").Value != null)
                        {
                            Common.IDType conceptAgency = new SDMX_Common.IDType();
                            conceptAgency.Value = dim.Attribute("conceptAgency").Value;
                            crossSectionalMeasure.ConceptAgency = conceptAgency;
                        }
                    }

                    if (dim.Attribute("conceptSchemaRef") != null)
                    {
                        if (dim.Attribute("conceptSchemaRef").Value != null)
                        {
                            Common.IDType conceptSchemaRef = new SDMX_Common.IDType();
                            conceptSchemaRef.Value = dim.Attribute("conceptSchemaRef").Value;
                            crossSectionalMeasure.ConceptSchemaRef = conceptSchemaRef;
                        }
                    }

                    if (dim.Attribute("conceptSchemaAgency") != null)
                    {
                        if (dim.Attribute("conceptSchemaAgency").Value != null)
                        {
                            Common.IDType conceptSchemaAgency = new SDMX_Common.IDType();
                            conceptSchemaAgency.Value = dim.Attribute("conceptSchemaAgency").Value;
                            crossSectionalMeasure.ConceptSchemaAgency = conceptSchemaAgency;
                        }
                    }

                    if (dim.Attribute("codelist") != null)
                    {
                        if (dim.Attribute("codelist").Value != null)
                        {
                            Common.IDType codelist = new SDMX_Common.IDType();
                            codelist.Value = dim.Attribute("codelist").Value;
                            crossSectionalMeasure.Codelist = codelist;
                        }
                    }

                    if (dim.Attribute("codelistVersion") != null)
                    {
                        if (dim.Attribute("codelistVersion").Value != null)
                        {
                            crossSectionalMeasure.CodelistVersion = dim.Attribute("codelistVersion").Value;
                        }
                    }

                    if (dim.Attribute("codelistAgency") != null)
                    {
                        if (dim.Attribute("codelistAgency").Value != null)
                        {
                            Common.IDType codelistAgency = new SDMX_Common.IDType();
                            codelistAgency.Value = dim.Attribute("codelistAgency").Value;
                            crossSectionalMeasure.Codelist = codelistAgency;
                        }
                    }

                     if (dim.Element(_nsStructur + "TextFormat") != null)
                    {
                        foreach (XElement textFormat in dim.Elements(_nsStructur + "TextFormat"))
                        {
                            crossSectionalMeasure.TextFormat.Add(ObjectBuilder.GetTextFormatType(textFormat));
                        }
                    }

                    if (dim.Element(_nsStructur + "Annotations") != null)
                    {
                        crossSectionalMeasure.Annotations = ObjectBuilder.GetAnnotationsType(dim.Element(_nsStructur + "Annotations"));
                    }

                    comp.Crosssectionalmeasure.Add(crossSectionalMeasure);


                }
                if(dim.Name == _nsStructur + "Attribute")
                {
                    SDMX_Structure.AttributeType a = new SDMX_Structure.AttributeType(new SDMX_Common.IDType(dim.Attribute("conceptRef").Value),
                        getAttachmentLevel(dim), getAssignmentStatus(dim));

                    if (dim.Attribute("conceptVersion") != null)
                    {
                        if (dim.Attribute("conceptVersion").Value != null)
                        {
                            a.ConceptVersion = dim.Attribute("conceptVersion").Value;
                        }
                    }

                    if (dim.Attribute("conceptAgency") != null)
                    {
                        if (dim.Attribute("conceptAgency").Value != null)
                        {
                            Common.IDType conceptAgency = new SDMX_Common.IDType();
                            conceptAgency.Value = dim.Attribute("conceptAgency").Value;
                            a.ConceptAgency = conceptAgency;
                        }
                    }

                    if (dim.Attribute("conceptSchemaRef") != null)
                    {
                        if (dim.Attribute("conceptSchemaRef").Value != null)
                        {
                            Common.IDType conceptSchemaRef = new SDMX_Common.IDType();
                            conceptSchemaRef.Value = dim.Attribute("conceptSchemaRef").Value;
                            a.ConceptSchemeRef = conceptSchemaRef;
                        }
                    }

                    if (dim.Attribute("conceptSchemaAgency") != null)
                    {
                        if (dim.Attribute("conceptSchemaAgency").Value != null)
                        {
                            Common.IDType conceptSchemaAgency = new SDMX_Common.IDType();
                            conceptSchemaAgency.Value = dim.Attribute("conceptSchemaAgency").Value;
                            a.ConceptSchemeAgency = conceptSchemaAgency;
                        }
                    }

                    if (dim.Attribute("codelist") != null)
                    {
                        if (dim.Attribute("codelist").Value != null)
                        {
                            Common.IDType codelist = new SDMX_Common.IDType();
                            codelist.Value = dim.Attribute("codelist").Value;
                            a.Codelist = codelist;
                        }
                    }

                    if (dim.Attribute("codelistVersion") != null)
                    {
                        if (dim.Attribute("codelistVersion").Value != null)
                        {
                            a.CodelistVersion = dim.Attribute("codelistVersion").Value;
                        }
                    }

                    if (dim.Attribute("codelistAgency") != null)
                    {
                        if (dim.Attribute("codelistAgency").Value != null)
                        {
                            Common.IDType codelistAgency = new SDMX_Common.IDType();
                            codelistAgency.Value = dim.Attribute("codelistAgency").Value;
                            a.Codelist = codelistAgency;
                        }
                    }

                    if (dim.Attribute("isTimeFormat") != null)
                    {
                        if (dim.Attribute("isTimeFormat").Value != null)
                        {
                            a.IsTimeFormat = Convert.ToBoolean(dim.Attribute("isTimeFormat").Value);
                        }
                    }

                    if (dim.Attribute("crossSectionalAttachDataSet") != null)
                    {
                        if (dim.Attribute("crossSectionalAttachDataSet").Value != null)
                        {
                            a.CrossSectionalAttachDataset = Convert.ToBoolean(dim.Attribute("crossSectionalAttachDataSet").Value);
                        }
                    }

                    if (dim.Attribute("crossSectionalAttachGroup") != null)
                    {
                        if (dim.Attribute("crossSectionalAttachGroup").Value != null)
                        {
                            a.CrossSectionalAttachGroup = Convert.ToBoolean(dim.Attribute("crossSectionalAttachGroup").Value);
                        }
                    }

                    if (dim.Attribute("crossSectionalAttachSection") != null)
                    {
                        if (dim.Attribute("crossSectionalAttachSection").Value != null)
                        {
                            a.CrossSectionalAttachSection = Convert.ToBoolean(dim.Attribute("crossSectionalAttachSection").Value);
                        }
                    }

                    if (dim.Attribute("crossSectionalAttachObservation") != null)
                    {
                        if (dim.Attribute("crossSectionalAttachObservation").Value != null)
                        {
                            a.CrossSectionalAttachObservation = Convert.ToBoolean(dim.Attribute("crossSectionalAttachObservation").Value);
                        }
                    }

                    if (dim.Attribute("isEntityAttribute") != null)
                    {
                        if (dim.Attribute("isEntityAttribute").Value != null)
                        {
                            a.IsEntityAttribute = Convert.ToBoolean(dim.Attribute("isEntityAttribute").Value);
                        }
                    }

                    if (dim.Attribute("isNonObservationalTimeAttribute") != null)
                    {
                        if (dim.Attribute("isNonObservationalTimeAttribute").Value != null)
                        {
                            a.IsNonObservationalTimeAttribute = Convert.ToBoolean(dim.Attribute("isNonObservationalTimeAttribute").Value);
                        }
                    }

                    if (dim.Attribute("isCountAttribute") != null)
                    {
                        if (dim.Attribute("isCountAttribute").Value != null)
                        {
                            a.IsCountAttribute = Convert.ToBoolean(dim.Attribute("isCountAttribute").Value);
                        }
                    }

                    if (dim.Attribute("isFrequencyAttribute") != null)
                    {
                        if (dim.Attribute("isFrequencyAttribute").Value != null)
                        {
                            a.IsFrequencyAttribute = Convert.ToBoolean(dim.Attribute("isFrequencyAttribute").Value);
                        }
                    }

                    if (dim.Attribute("isIdentityAttribute") != null)
                    {
                        if (dim.Attribute("isIdentityAttribute").Value != null)
                        {
                            a.IsIdentityAttribute = Convert.ToBoolean(dim.Attribute("isIdentityAttribute").Value);
                        }
                    }

                    if (dim.Element(_nsStructur + "TextFormat") != null)
                    {

                        foreach (XElement textFormat in dim.Elements(_nsStructur + "TextFormat"))
                        {
                            SDMX_Structure.TextFormatType textFormatType = new SDMX_Structure.TextFormatType();

                            a.TextFormat.Add(ObjectBuilder.GetTextFormatType(textFormat));
                        }
                    }

                    if (dim.Element(_nsStructur + "AttachmentGroup") != null)
                    {
                        if (dim.Element(_nsStructur + "AttachmentGroup").Value != null)
                        {
                            Common.IDType attachmentGroup = new SDMX_Common.IDType();
                            attachmentGroup.Value = dim.Element(_nsStructur + "AttachmentGroup").Value;
                            a.Codelist = attachmentGroup;
                        }
                    }

                    if (dim.Element(_nsStructur + "AttachmentMeasure") != null)
                    {
                        if (dim.Element(_nsStructur + "AttachmentMeasure").Value != null)
                        {
                            Common.IDType attachmentMeasure = new SDMX_Common.IDType();
                            attachmentMeasure.Value = dim.Element(_nsStructur + "AttachmentMeasure").Value;
                            a.Codelist = attachmentMeasure;
                        }
                    }

                    if (dim.Element(_nsStructur + "Annotations") != null)
                    {
                        a.Annotations = ObjectBuilder.GetAnnotationsType(dim.Element(_nsStructur + "Annotations"));
                    }
                    
                    comp.Attribute.Add(a);
                }
            }

            return comp;

        }

        private AttachmentLevel getAttachmentLevel(XElement element)
        {
            AttachmentLevel level;

            switch(element.Attribute("attachmentLevel").Value)
            {
                case "Series":
                    level = AttachmentLevel.Series;
                    break;
                case "DataSet":
                    level = AttachmentLevel.DataSet;
                    break;
                case "Group":
                    level = AttachmentLevel.Group;
                    break;
                case "Observation":
                    level = AttachmentLevel.Observation;
                    break;
                default:
                    level = AttachmentLevel.Any;
                    break;
            }

            return level;
        }

        private AssignmentStatus getAssignmentStatus(XElement element)
        {
            AssignmentStatus status;

            switch(element.Attribute("assignmentStatus").Value)
            {
                case "Conditional":
                    status = AssignmentStatus.Conditional;
                    break;
                default:
                    status = AssignmentStatus.Mandatory;
                    break;
            }

            return status;
        }

        /// <summary>
        /// Headertype for message.
        /// </summary>
        public SDMX_Message.HeaderType Header
        {
            get { return _header; }
            set { _header = value; }
        }

        /// <summary>
        /// Keyfamilies.
        /// </summary>
        public SDMX_Structure.KeyFamiliesType Keyfamilies
        {
            get { return _keyfamilies; }
            set { _keyfamilies = value; }
        }

        /// <summary>
        /// Codelists.
        /// </summary>
        public List<SDMX_Structure.CodelistType> Codelists
        {
            get { return _codelists; }
            set { _codelists = value; }
        }

        /// <summary>
        /// Concepts.
        /// </summary>
        public List<SDMX_Structure.ConceptType> Concepts
        {
            get { return _concepts; }
            set { _concepts = value; }
        }

        /// <summary>
        /// Conceptschemes.
        /// </summary>
        public List<SDMX_Structure.ConceptSchemeType> ConceptSchemes
        {
            get { return _conceptSchemes; }
            set { _conceptSchemes = value; }
        }

        /// <summary>
        /// CategoryScheme.
        /// </summary>
        public List<SDMX_Structure.CategorySchemeType> CategoryScheme
        {
            get { return _categorySchemes; }
            set { _categorySchemes = value; }
        }

        /// <summary>
        /// Get message as string.
        /// </summary>
        /// <returns>Xml as string.</returns>
        public string ToXml()
        {
            try
            {
                XElement x = GetXml();
                return x.ToString();
                //return _xmldoc.ToString();
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// Get message as XElement.
        /// </summary>
        /// <returns>Message as XElement.</returns>
        public XElement GetXml()
        {
            _xmldoc = new XDocument(
                new XDeclaration("1.0", "UTF-8", "yes"));
            
             XElement structure = new XElement(Namespaces.GetAllNamespaces("Structure"));

             if (_nsStructur == null)
             {
                 _nsCommon = Namespaces.GetNS("structure");
             }
 
             if (_header != null)
             {
                 structure.Add(_header.GetXml());
             }

             if (_categorySchemes.Count > 0)
             {
                 structure.Add(AddCategoryScheme());
             }

            if (_codelists.Count > 0)
            {
                structure.Add(addCodelist());
            }

            if (_hierarchicalcodelists.Count > 0)
            {
                structure.Add(AddHierarchicalCodelists());
            }

            if (_concepts.Count > 0)
            {
                structure.Add(addConcept());
            }

            if (_keyfamilies.KeyFamily.Count > 0)
            {
                structure.Add(addKeyFamilies());
            }

             return structure;
        }

        #region HierarchicalCodelists

        private XElement AddHierarchicalCodelists()
        {
            //Root element for all category schemes.
            XElement hierarchicalCodelists = new XElement(Namespaces.GetNS("message") + "HierarchicalCodelists");

            foreach (SDMX_Structure.HierarchicalCodelistType hierarchicalCodelistType in _hierarchicalcodelists)
            {
                XElement hierarchicalCodelist = new XElement(_nsStructur + "HierarchicalCodelist");

                //Elements

                if (hierarchicalCodelistType.Name != null)
                {
                    foreach (SDMX_Common.TextType name in hierarchicalCodelistType.Name)
                    {
                        hierarchicalCodelist.Add(ElementBuilder.GetTextType(name, "Name", _nsStructur));
                    }
                }
                else
                {
                    throw new Exception("Name is a required element in HierarchicalCodelistsType.");
                }

                if (hierarchicalCodelistType.Description != null)
                {
                    foreach (SDMX_Common.TextType description in hierarchicalCodelistType.Description)
                    {
                        hierarchicalCodelist.Add(ElementBuilder.GetTextType(description, "Description", _nsStructur));
                    }
                }

                if (hierarchicalCodelistType.CodelistRef != null)
                {
                    foreach (SDMX_Structure.CodelistRefType codelistRef in hierarchicalCodelistType.CodelistRef)
                    {
                        hierarchicalCodelist.Add(AddCodelistRef(codelistRef));
                    }
                }

                if (hierarchicalCodelistType.Hierarchy != null)
                {
                    foreach (SDMX_Structure.HierarchyType hierarchy in hierarchicalCodelistType.Hierarchy)
                    {
                        hierarchicalCodelist.Add(AddHierarchy(hierarchy));
                    }
                }

                if (hierarchicalCodelistType.Annotations != null)
                {
                    hierarchicalCodelist.Add(ElementBuilder.GetAnnotations(hierarchicalCodelistType.Annotations, _nsStructur));
                }

                if (hierarchicalCodelistType.Id != null)
                {
                    if (!String.IsNullOrEmpty(hierarchicalCodelistType.Id.Value))
                    {
                        hierarchicalCodelist.Add(new XAttribute("id", hierarchicalCodelistType.Id.Value));
                    }
                    else
                    {
                        throw new Exception("Value in attribute id in HierarchicalCodelists is required.");
                    }
                }
                else
                {
                    throw new Exception("Attribute id is required in HierarchicalCodelists.");
                }

                if (hierarchicalCodelistType.AgencyID != null)
                {
                    if (!String.IsNullOrEmpty(hierarchicalCodelistType.AgencyID.Value))
                    {
                        hierarchicalCodelist.Add(new XAttribute("agencyID", hierarchicalCodelistType.AgencyID.Value));
                    }
                }

                if (!String.IsNullOrEmpty(hierarchicalCodelistType.Version))
                {
                    hierarchicalCodelist.Add(new XAttribute("version", hierarchicalCodelistType.Version));
                }

                if (!String.IsNullOrEmpty(hierarchicalCodelistType.Urn))
                {
                    hierarchicalCodelist.Add(new XAttribute("urn", hierarchicalCodelistType.Urn));
                }

                if (!String.IsNullOrEmpty(hierarchicalCodelistType.Uri))
                {
                    hierarchicalCodelist.Add(new XAttribute("uri", hierarchicalCodelistType.Uri));
                }

                if (hierarchicalCodelistType.IsExternalReference != null)
                {
                    hierarchicalCodelist.Add(new XAttribute("isExternalReference", hierarchicalCodelistType.IsExternalReference.ToString().ToLower()));
                }

                if (hierarchicalCodelistType.IsFinal != null)
                {
                    hierarchicalCodelist.Add(new XAttribute("isFinal", hierarchicalCodelistType.IsFinal.ToString().ToLower()));
                }

                if (!String.IsNullOrEmpty(hierarchicalCodelistType.ValidFrom))
                {
                    hierarchicalCodelist.Add(new XAttribute("validFrom", hierarchicalCodelistType.ValidFrom));
                }

                if (!String.IsNullOrEmpty(hierarchicalCodelistType.ValidTo))
                {
                    hierarchicalCodelist.Add(new XAttribute("validTo", hierarchicalCodelistType.ValidTo));
                }

                hierarchicalCodelists.Add(hierarchicalCodelist);
            }

           

            return hierarchicalCodelists;
        }

        private XElement AddHierarchy(SDMX_Structure.HierarchyType hierarchyType)
        {
            XElement hierarcy = new XElement(_nsStructur + "Hierarchy");

            if (hierarchyType.Name != null)
            {
                foreach (SDMX_Common.TextType name in hierarchyType.Name)
                {
                    if (!String.IsNullOrEmpty(name.Text))
                    {
                        hierarcy.Add(ElementBuilder.GetTextType(name, "Name", _nsStructur));
                    }
                    else
                    {
                        throw new Exception("Value in element Name is required.");
                    }
                }
            }
            else
            {
                throw new Exception("Element Name is required in HierarchyType.");
            }

            if (hierarchyType.Description != null)
            {
                foreach (SDMX_Common.TextType desc in hierarchyType.Description)
                {
                    if (!String.IsNullOrEmpty(desc.Text))
                    {
                        hierarcy.Add(ElementBuilder.GetTextType(desc, "Description", _nsStructur));
                    }
                }
            }

            if (hierarchyType.CodeRef != null)
            {
                foreach (SDMX_Structure.CodeRefType codeRef in hierarchyType.CodeRef)
                {
                    hierarcy.Add(AddCodeRefType(codeRef));
                }
            }

            if (hierarchyType.Level != null)
            {
                foreach (SDMX_Structure.LevelType levelType in hierarchyType.Level)
                {
                    hierarcy.Add(AddLevelType(levelType));
                }
            }

            if (hierarchyType.Annotations != null)
            {
                hierarcy.Add(ElementBuilder.GetAnnotations(hierarchyType.Annotations, _nsStructur));
            }

            if (hierarchyType.Id != null)
            {
                if (!String.IsNullOrEmpty(hierarchyType.Id.Value))
                {
                    hierarcy.Add(new XAttribute("id", hierarchyType.Id.Value));
                }
                else
                {
                    throw new Exception("Value in attribute id in HierarchyType is required.");
                }
            }
            else
            {
                throw new Exception("Attribute id is required in HierarchyType.");
            }

            if (!String.IsNullOrEmpty(hierarchyType.Urn))
            {
                hierarcy.Add(new XAttribute("urn", hierarchyType.Urn));
            }

            if (!String.IsNullOrEmpty(hierarchyType.Version))
            {
                hierarcy.Add(new XAttribute("version", hierarchyType.Version));
            }

            if (hierarchyType.IsFinal != null)
            {
                hierarcy.Add(new XAttribute("isFinal", hierarchyType.IsFinal.ToString().ToLower()));
            }

            if (!String.IsNullOrEmpty(hierarchyType.ValidFrom))
            {
                hierarcy.Add(new XAttribute("validFrom", hierarchyType.ValidFrom));
            }

            if (!String.IsNullOrEmpty(hierarchyType.ValidTo))
            {
                hierarcy.Add(new XAttribute("validTo", hierarchyType.ValidTo));
            }
           

            return hierarcy;
        }

        private XElement AddCodeRefType(SDMX_Structure.CodeRefType codeRefType)
        {
            XElement codeRef = new XElement(_nsStructur + "CodeRef");

            if (!String.IsNullOrEmpty(codeRefType.Urn))
            {
                codeRef.Add(new XElement(_nsStructur + "URN", codeRefType.Urn));
            }

            if (codeRefType.CodelistAliasRef != null)
            {
                if(!String.IsNullOrEmpty(codeRefType.CodelistAliasRef.Value))
                {
                    codeRef.Add(new XElement(_nsStructur + "CodelistAliasRef", codeRefType.CodelistAliasRef.Value));
                }
            }

            if (codeRefType.CodeID != null)
            {
                if (!String.IsNullOrEmpty(codeRefType.CodeID.Value))
                {
                    codeRef.Add(new XElement(_nsStructur + "CodeID", codeRefType.CodeID.Value));
                }
            }

            if (codeRefType.CodeRefType1 != null)
            {
                foreach(SDMX_Structure.CodeRefType crType in codeRefType.CodeRefType1)
                {
                    codeRef.Add(AddCodeRefType(crType));
                }
            }

            if (codeRefType.LevelRef != null)
            {
                if (!String.IsNullOrEmpty(codeRefType.LevelRef.Value))
                {
                    codeRef.Add(new XElement(_nsStructur + "LevelRef", codeRefType.LevelRef.Value));
                }
            }

            if (!String.IsNullOrEmpty(codeRefType.NodeAliasID))
            {
                codeRef.Add(new XElement(_nsStructur + "NodeAliasID", codeRefType.NodeAliasID));
            }

            if (!String.IsNullOrEmpty(codeRefType.Version))
            {
                codeRef.Add(new XElement(_nsStructur + "Version", codeRefType.Version));
            }

            if (!String.IsNullOrEmpty(codeRefType.ValidFrom))
            {
                codeRef.Add(new XElement(_nsStructur + "ValidFrom", codeRefType.ValidFrom));
            }

            if (!String.IsNullOrEmpty(codeRefType.ValidTo))
            {
                codeRef.Add(new XElement(_nsStructur + "ValidTo", codeRefType.ValidTo));
            }

            return codeRef;
        }

        private XElement AddCodelistRef(SDMX_Structure.CodelistRefType codelistRefType)
        {
            XElement codelistRef = new XElement(_nsStructur + "CodelistRef");

            if (!String.IsNullOrEmpty(codelistRefType.Urn))
            {
                codelistRef.Add(new XElement(_nsStructur + "URN", codelistRefType.Urn));
            }

            if (codelistRefType.AgencyID != null)
            {
                if (!String.IsNullOrEmpty(codelistRefType.AgencyID.Value))
                {
                    codelistRef.Add(new XElement(_nsStructur + "AgencyID", codelistRefType.AgencyID.Value));
                }
            }

            if (codelistRefType.CodelistID != null)
            {
                if (!String.IsNullOrEmpty(codelistRefType.CodelistID.Value))
                {
                    codelistRef.Add(new XElement(_nsStructur + "CodelistID", codelistRefType.CodelistID.Value));
                }
            }

            if (!String.IsNullOrEmpty(codelistRefType.Version))
            {
                codelistRef.Add(new XElement(_nsStructur + "Version", codelistRefType.Version));
            }

            if (codelistRefType.Alias != null)
            {
                if (!String.IsNullOrEmpty(codelistRefType.Alias.Value))
                {
                    codelistRef.Add(new XElement(_nsStructur + "Alias", codelistRefType.Alias.Value));
                }
            }

            return codelistRef;
        }

        private XElement AddLevelType(SDMX_Structure.LevelType levelType)
        {
            XElement level = new XElement(_nsStructur + "Level");

            if (levelType.Name != null)
            {
                foreach (SDMX_Common.TextType name in levelType.Name)
                {
                    if (!String.IsNullOrEmpty(name.Text))
                    {
                        level.Add(ElementBuilder.GetTextType(name, "Name", _nsStructur));
                    }
                    else
                    {
                        throw new Exception("Value in element Name is required.");
                    }
                }
            }
            else
            {
                throw new Exception("Element Name is required in LevelType.");
            }

            if (levelType.Description != null)
            {
                foreach (SDMX_Common.TextType desc in levelType.Description)
                {
                    if (!String.IsNullOrEmpty(desc.Text))
                    {
                        level.Add(ElementBuilder.GetTextType(desc, "Description", _nsStructur));
                    }
                }
            }

            if (levelType.Order != null)
            {
                level.Add(new XElement(_nsStructur + "Order", levelType.Order));
            }
            else
            {
                throw new Exception("Order is required in LevelType.");
            }

            if (levelType.CodingType != null)
            {
                level.Add(new XElement(_nsStructur + "CodingType", ElementBuilder.GetTextFormatType(levelType.CodingType)));
            }

            if (levelType.Annotations != null)
            {
                level.Add(ElementBuilder.GetAnnotations(levelType.Annotations, _nsStructur));
            }

            if (levelType.Id != null)
            {
                if (!String.IsNullOrEmpty(levelType.Id.Value))
                {
                    level.Add(new XAttribute("id", levelType.Id.Value));
                }
                else
                {
                    throw new Exception("Value in attribute id is required.");
                }
            }
            else
            {
                throw new Exception("Attribute id is required in LevelType");
            }

            if (!String.IsNullOrEmpty(levelType.Urn))
            {
                level.Add(new XAttribute("urn", levelType.Urn));
            }

            return level;
        }


        #endregion

        #region Category Scheme


        private XElement AddCategoryScheme()
        {
            //Root element for all category schemes.
            XElement categorySchemes = new XElement(_nsMessage + "CategorySchemes");

            foreach (SDMX_Structure.CategorySchemeType categorySchemeType in _categorySchemes)
            {
                XElement categoryScheme = new XElement(_nsStructur + "CategoryScheme");

                //Elements

                if (categorySchemeType.Name != null)
                {
                    foreach (SDMX_Common.TextType name in categorySchemeType.Name)
                    {
                        categoryScheme.Add(ElementBuilder.GetTextType(name, "Name", _nsStructur));
                    }
                }
                else
                {
                    throw new Exception("Name is a required element in CategorySchemeType.");
                }

                if (categorySchemeType.Description != null)
                {
                    foreach (SDMX_Common.TextType description in categorySchemeType.Description)
                    {
                        categoryScheme.Add(ElementBuilder.GetTextType(description, "Description", _nsStructur));
                    }
                }

                if (categorySchemeType.Category != null)
                {
                    foreach (SDMX_Structure.CategoryType category in categorySchemeType.Category)
                    {
                        categoryScheme.Add(AddCategoryType(category));
                    }
                }

                if (categorySchemeType.Annotations != null)
                {
                    categoryScheme.Add(ElementBuilder.GetAnnotations(categorySchemeType.Annotations, _nsStructur));
                }


                //Attributes

                if (categorySchemeType.ID != null)
                {
                    if (!String.IsNullOrEmpty(categorySchemeType.ID.Value))
                    {
                        categoryScheme.Add(new XAttribute("id", categorySchemeType.ID.Value));
                    }
                    else
                    {
                        throw new Exception("Value in attribute ID in CategoryScheme is required.");
                    }
                }
                else
                {
                    throw new Exception("Attribute ID  is required in CategorySchemeType.");
                }

                if (categorySchemeType.AgencyID != null)
                {
                    if (!String.IsNullOrEmpty(categorySchemeType.AgencyID.Value))
                    {
                        categoryScheme.Add(new XAttribute("agencyID", categorySchemeType.AgencyID.Value));
                    }
                    else
                    {
                        throw new Exception("Value in attribute agencyID in CategoryScheme is required.");
                    }
                }
                else
                {
                    throw new Exception("Attribute agencyID  is required in CategorySchemeType.");
                }

                if (!String.IsNullOrEmpty(categorySchemeType.Version))
                {
                    categoryScheme.Add(new XAttribute("version", categorySchemeType.Version));
                }

                if (!String.IsNullOrEmpty(categorySchemeType.URN))
                {
                    categoryScheme.Add(new XAttribute("urn", categorySchemeType.URN));
                }

                if (!String.IsNullOrEmpty(categorySchemeType.URI))
                {
                    categoryScheme.Add(new XAttribute("uri", categorySchemeType.URI));
                }

                if (categorySchemeType.IsExternalReference != null)
                {
                    categoryScheme.Add(new XAttribute("isExternalReference", categorySchemeType.IsExternalReference.ToString()));
                }

                if (categorySchemeType.IsFinal != null)
                {
                    categoryScheme.Add(new XAttribute("isExternalReference", categorySchemeType.IsFinal.ToString().ToLower()));
                }

                if (!String.IsNullOrEmpty(categorySchemeType.ValidFrom))
                {
                    categoryScheme.Add(new XAttribute("validFrom", categorySchemeType.ValidFrom));
                }

                if (!String.IsNullOrEmpty(categorySchemeType.ValidTo))
                {
                    categoryScheme.Add(new XAttribute("validTo", categorySchemeType.ValidTo));
                }

                categorySchemes.Add(categoryScheme);
            }

            return categorySchemes;
        }

        private XElement AddCategoryType(SDMX_Structure.CategoryType catType)
        {
            XElement categoryType = new XElement(_nsStructur + "Category");

            if (catType.Name != null)
            {
                foreach (SDMX_Common.TextType name in catType.Name)
                {
                    if (!String.IsNullOrEmpty(name.Text))
                    {
                        categoryType.Add(ElementBuilder.GetTextType(name, "Name", _nsStructur));
                    }
                }
            }
            else
            {
                throw new Exception("Name is a required element in CategoryType.");
            }

            if (catType.ID != null)
            {
                if (catType.ID.Value != null)
                {
                    categoryType.Add(new XAttribute("id", catType.ID.Value));
                }
                else
                {
                    throw new Exception("Value in attribute id in CategoryType is required.");
                }
            }
            else
            {
                throw new Exception("Attribute id is required in CategoryTYpe.");
            }

            if (!String.IsNullOrEmpty(catType.Version))
            {
                categoryType.Add(new XAttribute("version", catType.Version));
            }

            if (!String.IsNullOrEmpty(catType.URN))
            {
                categoryType.Add(new XAttribute("urn", catType.URN));
            }

            if (!String.IsNullOrEmpty(catType.URI))
            {
                categoryType.Add(new XAttribute("uri", catType.URI));
            }

            if (catType.IsExternalReference != null)
            {
                categoryType.Add(new XAttribute("isExternalReference", catType.IsExternalReference.ToString().ToLower()));
            }
            

            if (catType.Description != null)
            {
                foreach (SDMX_Common.TextType description in catType.Description)
                {
                    if (!String.IsNullOrEmpty(description.Text))
                    {
                        categoryType.Add(ElementBuilder.GetTextType(description, "Description", _nsStructur));
                    }
                }
            }

            if (catType.DataFlowRef != null)
            {
                foreach (SDMX_Structure.DataflowRefType dataflowRef in catType.DataFlowRef)
                {
                    categoryType.Add(AddDataFlowRef(dataflowRef));
                }
            }

            if (catType.MetadataFlowRef != null)
            {
                foreach (SDMX_Structure.MetadataflowRefType metaDataflowRef in catType.MetadataFlowRef)
                {
                    categoryType.Add(AddMetaDataFlowRef(metaDataflowRef));
                }
            }

            if (catType.Category != null)
            {
                foreach (SDMX_Structure.CategoryType category in catType.Category)
                {
                    categoryType.Add(AddCategoryType(category));
                }
            }

            if (catType.Annotations != null)
            {
                categoryType.Add(ElementBuilder.GetAnnotations(catType.Annotations, _nsStructur));
            }

            return categoryType;
        }

        private XElement AddDataFlowRef(SDMX_Structure.DataflowRefType dataflowRefType)
        {
            XElement dataflowRef = new XElement(_nsStructur + "DataflowRef");

            if (dataflowRefType.URN != null)
            {
                foreach (string urn in dataflowRefType.URN)
                {
                    if (!String.IsNullOrEmpty(urn))
                    {
                        dataflowRef.Add(new XElement(_nsStructur + "URN", urn));
                    }
                }
            }

            
            if (dataflowRefType.AgencyID != null)
            {
                foreach (SDMX_Common.IDType agencyID in dataflowRefType.AgencyID)
                {
                    if (!String.IsNullOrEmpty(agencyID.Value))
                    {
                        dataflowRef.Add(new XElement(_nsStructur + "AgencyID", agencyID.Value));
                    }
                }
            }

            if (dataflowRefType.DataFlowID != null)
            {
                foreach (SDMX_Common.IDType dataFlowID in dataflowRefType.DataFlowID)
                {
                    if (!String.IsNullOrEmpty(dataFlowID.Value))
                    {
                        dataflowRef.Add(new XElement(_nsStructur + "DataflowID", dataFlowID.Value));
                    }
                }
            }

            if (dataflowRefType.Version != null)
            {
                foreach (string version in dataflowRefType.Version)
                {
                    if (!String.IsNullOrEmpty(version))
                    {
                        dataflowRef.Add(new XElement(_nsStructur + "Version", version));
                    }
                }
            }

            return dataflowRef;
        }

        private XElement AddMetaDataFlowRef(SDMX_Structure.MetadataflowRefType metaDataflowRefType)
        {
            XElement metaDataflowRef = new XElement(_nsStructur + "DataflowRef");

            if (metaDataflowRefType.URN != null)
            {
                foreach (string urn in metaDataflowRefType.URN)
                {
                    if (!String.IsNullOrEmpty(urn))
                    {
                        metaDataflowRef.Add(new XElement(_nsStructur + "URN", urn));
                    }
                }
            }

            if (metaDataflowRefType.AgencyID != null)
            {
                foreach (SDMX_Common.IDType agencyID in metaDataflowRefType.AgencyID)
                {
                    if (!String.IsNullOrEmpty(agencyID.Value))
                    {
                        metaDataflowRef.Add(new XElement(_nsStructur + "AgencyID", agencyID.Value));
                    }
                }
            }

            if (metaDataflowRefType.MetadataFlowID != null)
            {
                foreach (SDMX_Common.IDType metadataFlowID in metaDataflowRefType.MetadataFlowID)
                {
                    if (!String.IsNullOrEmpty(metadataFlowID.Value))
                    {
                        metaDataflowRef.Add(new XElement(_nsStructur + "MetadataflowID", metadataFlowID.Value));
                    }
                }
            }

            if (metaDataflowRefType.Version != null)
            {
                foreach (string version in metaDataflowRefType.Version)
                {
                    if (!String.IsNullOrEmpty(version))
                    {
                        metaDataflowRef.Add(new XElement(_nsStructur + "Version", version));
                    }
                }
            }

            return metaDataflowRef;
        }

        #endregion

        #region Codelist

        private XElement addCodelist()
        {
            XElement codelists = new XElement(_nsMessage + "CodeLists");

            foreach(SDMX_Structure.CodelistType c in _codelists)
            {
                if(c.Id != null)
                {
                    XElement codelist = new XElement(_nsStructur + "CodeList");
                    codelist.Add(new XAttribute("id", c.Id));

                    if (c.Agencyid != null)
                    {
                        codelist.Add(new XAttribute("agencyID", c.Agencyid));
                    }
                    else
                    {
                        throw new Exception("AgencyId attribute is missing in codelist: " + c.Id);
                    }

                    if (c.Version != null)
                    {
                        codelist.Add(new XAttribute("version", c.Version));
                    }

                    if(c.Uri != null)
                    {
                        codelist.Add(new XAttribute("uri", c.Uri));
                    }

                    if (c.Urn != null)
                    {
                        codelist.Add(new XAttribute("urn", c.Urn));
                    }

                    if (c.IsExternalReference != null)
                    {
                        codelist.Add(new XAttribute("isExternalReference", c.IsExternalReference));
                    }

                    if (c.IsFinal != null)
                    {
                        codelist.Add(new XAttribute("isFinal", c.IsFinal));
                    }

                    if (c.ValidFrom != null)
                    {
                        codelist.Add(new XAttribute("validFrom", c.ValidFrom));
                    }

                    if (c.ValidTo != null)
                    {
                        codelist.Add(new XAttribute("validTo", c.ValidTo));
                    }

                    if (c.Name.Count > 0)
                    {
                        foreach (SDMX_Common.TextType name in c.Name)
                        {
                            if (name.Text != null)
                            {
                                XElement enName = new XElement(_nsStructur + "Name", name.Text);

                                if (name.Lang != null)
                                {
                                    enName.Add(new XAttribute(XNamespace.Xml + "lang", name.Lang));
                                }

                                codelist.Add(enName);
                            }
                        }
                    }
                    else
                    {
                        throw new Exception("At least one name should be added to the codelist.");
                    }

                    if (c.Description.Count > 0)
                    {
                        foreach (SDMX_Common.TextType description in c.Description)
                        {
                            if (description.Text != null)
                            {
                                XElement enDescription = new XElement(_nsStructur + "Name", description.Text);

                                if (description.Lang != null)
                                {
                                    enDescription.Add(new XAttribute(XNamespace.Xml + "lang", description.Lang));
                                }

                                codelist.Add(enDescription);
                            }
                        }
                    }

                    

                    codelist = addCodevalues(c, codelist);

                    if (c.Annotations != null)
                    {
                            XElement annotations = ElementBuilder.GetAnnotations(c.Annotations, _nsStructur);

                            codelist.Add(annotations);
                    }

                    codelists.Add(codelist);
                }
                else
                {
                    throw new Exception("Id attribute is missing.");
                }
            }

            return codelists;
        }

        private XElement addCodevalues(SDMX_Structure.CodelistType codelist, XElement element)
        {
            foreach(SDMX_Structure.CodeType c in codelist.Codevalues)
            {
                XElement code = new XElement(_nsStructur + "Code");
                 
                if(c.Value != null)
                {
                    SDMX_Common.IDType codeValue = c.Value;

                    code.Add(new XAttribute("value", codeValue.Value));
                }

                if (c.Urn != null)
                {
                    code.Add(new XAttribute("urn", c.Urn));
                }

                if (c.ParentCode != null)
                {
                    code.Add(new XAttribute("parentCode", c.ParentCode));
                }

                if(c.Description.Count > 0)
                {

                    foreach (SDMX_Common.TextType desc in c.Description)
                    {

                        if (desc.Text != null)
                        {
                            XElement enDesc = new XElement(_nsStructur + "Description", desc.Text);

                            if (desc.Lang != null)
                            {
                                enDesc.Add(new XAttribute(XNamespace.Xml + "lang", desc.Lang));
                            }

                            code.Add(enDesc);
                        }
                    }
                }

                if (c.Annotations != null)
                {
                    code.Add(ElementBuilder.GetAnnotations(c.Annotations, _nsStructur));
                }

                element.Add(code);
            }

            return element;
        }

        #endregion

        #region Concept

         private XElement addConcept()
        {
            XElement concepts = new XElement(_nsMessage+ "Concepts");

            foreach(SDMX_Structure.ConceptType conceptType in _concepts)
            {
                XElement concept = GetConceptXElement(conceptType);

                concepts.Add(concept);
            }

            foreach (SDMX_Structure.ConceptSchemeType conceptSchemeType in _conceptSchemes)
            {
                XElement conceptScheme = new XElement(_nsStructur + "ConceptScheme");

                if (conceptSchemeType.Id != null)
                {
                    conceptScheme.Add(new XAttribute("id", conceptSchemeType.Id));

                    if (conceptSchemeType.AgencyID != null)
                    {
                        conceptScheme.Add(new XAttribute("agencyID", conceptSchemeType.AgencyID));
                    }
                    else
                    {
                        throw new Exception("AgencyId attribute is missing in concept: " + conceptSchemeType.Id);
                    }

                    if (conceptSchemeType.Version != null)
                    {
                        conceptScheme.Add(new XAttribute("version", conceptSchemeType.Version));
                    }

                    if (conceptSchemeType.Uri != null)
                    {
                        conceptScheme.Add(new XAttribute("uri", conceptSchemeType.Uri));
                    }

                    if (conceptSchemeType.Urn != null)
                    {
                        conceptScheme.Add(new XAttribute("urn", conceptSchemeType.Urn));
                    }

                    if (conceptSchemeType.IsExternalReference != null)
                    {
                        conceptScheme.Add(new XAttribute("isExternalReference", conceptSchemeType.IsExternalReference));
                    }

                    if (conceptSchemeType.IsFinal != null)
                    {
                        conceptScheme.Add(new XAttribute("isFinal", conceptSchemeType.IsFinal));
                    }

                    if (conceptSchemeType.ValidFrom != null)
                    {
                        conceptScheme.Add(new XAttribute("validFrom", conceptSchemeType.ValidFrom));
                    }

                    if (conceptSchemeType.ValidTo != null)
                    {
                        conceptScheme.Add(new XAttribute("validTo", conceptSchemeType.ValidTo));
                    }
                }
                else
                {
                    throw new Exception("Id attribute is missing in concept.");
                }


                if (conceptSchemeType.Name.Count > 0)
                {
                    foreach (SDMX_Common.TextType name in conceptSchemeType.Name)
                    {
                        if (name.Text != null)
                        {
                            XElement enName = new XElement(_nsStructur + "Name", name.Text);

                            if (name.Lang != null)
                            {
                                enName.Add(new XAttribute(XNamespace.Xml + "lang", name.Lang));
                            }

                            conceptScheme.Add(enName);
                        }
                    }
                }
                else
                {
                    throw new Exception("At least one name should be added to the ConceptSchme.");
                }

                if (conceptSchemeType.Description.Count > 0)
                {
                    foreach (SDMX_Common.TextType description in conceptSchemeType.Description)
                    {
                        if (description.Text != null)
                        {
                            XElement enDescription = new XElement(_nsStructur + "Name", description.Text);

                            if (description.Lang != null)
                            {
                                enDescription.Add(new XAttribute(XNamespace.Xml + "lang", description.Lang));
                            }

                            conceptScheme.Add(enDescription);
                        }
                    }
                }

                if (conceptSchemeType.Concept.Count > 0)
                {
                    foreach(SDMX_Structure.ConceptType conceptType in conceptSchemeType.Concept)
                    {
                        XElement concept = GetConceptXElement(conceptType);
                        conceptScheme.Add(concept);
                    }
                }

                if (conceptSchemeType.Annotations != null)
                {
                    XElement annotations = ElementBuilder.GetAnnotations(conceptSchemeType.Annotations, _nsStructur);

                    conceptScheme.Add(annotations);
                }

                concepts.Add(conceptScheme);
            }

            return concepts;
        }

        private XElement GetConceptXElement(SDMX_Structure.ConceptType conceptType)
        {
            XElement concept = new XElement(_nsStructur + "Concept");

            if (conceptType.ID != null)
            {
                if(conceptType.ID.Value != null)
                {
                    concept.Add(new XAttribute("id", conceptType.ID.Value));
                }

                if (conceptType.AgencyID != null)
                {
                    if (conceptType.AgencyID.Value != null)
                    {
                        concept.Add(new XAttribute("agencyID", conceptType.AgencyID.Value));
                    }
                }

                if (conceptType.Version != null)
                {
                    concept.Add(new XAttribute("version", conceptType.Version));
                }

                if (conceptType.Uri != null)
                {
                    concept.Add(new XAttribute("uri", conceptType.Uri));
                }

                if (conceptType.Urn != null)
                {
                    concept.Add(new XAttribute("urn", conceptType.Urn));
                }

                if (conceptType.IsExternalReference != null)
                {
                    concept.Add(new XAttribute("isExternalReference", conceptType.IsExternalReference));
                }

                if (conceptType.CoreRepresentation != null)
                {
                    concept.Add(new XAttribute("corePresentation", conceptType.CoreRepresentation.Value));
                }

                if (conceptType.CoreReprensentationAgency != null)
                {
                    concept.Add(new XAttribute("coreReprensentationAgency", conceptType.CoreReprensentationAgency.Value));
                }

                if (conceptType.Parent != null)
                {
                    concept.Add(new XAttribute("parent", conceptType.Parent.Value));
                }

                if (conceptType.ParentAgency != null)
                {
                    concept.Add(new XAttribute("parentAgency", conceptType.ParentAgency.Value));
                }
            }
            else
            {
                throw new Exception("Id attribute is missing in concept.");
            }

            if (conceptType.Name.Count > 0)
            {
                foreach (SDMX_Common.TextType name in conceptType.Name)
                {
                    if (name.Text != null)
                    {
                        XElement enName = new XElement(_nsStructur + "Name", name.Text);

                        if (name.Lang != null)
                        {
                            enName.Add(new XAttribute(XNamespace.Xml + "lang", name.Lang));
                        }

                        concept.Add(enName);
                    }
                }
            }
            else
            {
                throw new Exception("At least one name should be added to the concept.");
            }

            if (conceptType.Description.Count > 0)
            {
                foreach (SDMX_Common.TextType description in conceptType.Description)
                {
                    if (description.Text != null)
                    {
                        XElement enDescription = new XElement(_nsStructur + "Name", description.Text);

                        if (description.Lang != null)
                        {
                            enDescription.Add(new XAttribute(XNamespace.Xml + "lang", description.Lang));
                        }

                        concept.Add(enDescription);
                    }
                }
            }

            if (conceptType.Textformat != null)
            {
                XElement textFormat = new XElement(_nsStructur + "TextFormat");

                SDMX_Structure.TextFormatType textFormatType = conceptType.Textformat;

                if (textFormatType.Texttype != null)
                {
                    textFormat.Add(new XAttribute("textType", textFormatType.Texttype.Value.ToString()));
                }

                if (textFormatType.IsSequence != null)
                {
                    textFormat.Add(new XAttribute("isSequence", textFormatType.IsSequence));
                }

                if (textFormatType.Minlength != null)
                {
                    textFormat.Add(new XAttribute("minLength", textFormatType.Minlength));
                }

                if (textFormatType.Maxlength != null)
                {
                    textFormat.Add(new XAttribute("maxLength", textFormatType.Maxlength));
                }

                if (textFormatType.Startvalue != null)
                {
                    textFormat.Add(new XAttribute("startValue", textFormatType.Startvalue));
                }

                if (textFormatType.Endvalue != null)
                {
                    textFormat.Add(new XAttribute("endValue", textFormatType.Endvalue));
                }

                if (textFormatType.Interval != null)
                {
                    textFormat.Add(new XAttribute("interval", textFormatType.Interval));
                }

                if (textFormatType.Timeinterval != null)
                {
                    textFormat.Add(new XAttribute("timeInterval", textFormatType.Timeinterval));
                }

                if (textFormatType.Decimals != null)
                {
                    textFormat.Add(new XAttribute("decimals", textFormatType.Decimals));
                }

                if (textFormatType.Pattern != null)
                {
                    textFormat.Add(new XAttribute("pattern", textFormatType.Pattern));
                }

                concept.Add(textFormat);

            }


            if (conceptType.Annotations != null)
            {
                XElement annotations = ElementBuilder.GetAnnotations(conceptType.Annotations, _nsStructur);

                concept.Add(annotations);
            }

            return concept;
            
        }

        #endregion

        #region KeyFamily

        private XElement addKeyFamilies()
        {
            XElement keyfamilies = new XElement(_nsMessage + "KeyFamilies");

            foreach(SDMX_Structure.KeyFamilyType kf in _keyfamilies.KeyFamily)
            {
                XElement keyfamily = new XElement(_nsStructur + "KeyFamily");

                if (kf.ID != null)
                {
                    keyfamily.Add(new XAttribute("agencyID", kf.ID.Value));
                }
                else
                {
                    throw new Exception("The attribute id is missing in KeyFamily");
                }

                if (kf.AgencyID != null)
                {
                    keyfamily.Add(new XAttribute("id", kf.AgencyID.Value));
                }
                else
                {
                    throw new Exception("The attribute agencyId is missing in KeyFamily");
                }

                if (!String.IsNullOrEmpty(kf.Version))
                {
                    keyfamily.Add(new XAttribute("version", kf.Version));
                }

                if (!String.IsNullOrEmpty(kf.Uri))
                {
                    keyfamily.Add(new XAttribute("uri", kf.Uri));
                }

                if (!String.IsNullOrEmpty(kf.Urn))
                {
                    keyfamily.Add(new XAttribute("urn", kf.Urn));
                }

                if (kf.Isfinal != null)
                {
                    keyfamily.Add(new XAttribute("isFinal", kf.Isfinal));
                }

                if (kf.IsExternalReference != null)
                {
                    keyfamily.Add(new XAttribute("isExternalReference", kf.IsExternalReference));
                }

                if (!String.IsNullOrEmpty(kf.ValidFrom))
                {
                    keyfamily.Add(new XAttribute("validFrom", kf.ValidFrom));
                }

                if (!String.IsNullOrEmpty(kf.ValidTo))
                {
                    keyfamily.Add(new XAttribute("validTo", kf.ValidTo));
                }

                if (kf.Name.Count > 0)
                {
                    foreach (SDMX_Common.TextType name in kf.Name)
                    {
                        if (name.Text != null)
                        {
                            XElement enName = new XElement(_nsStructur + "Name", name.Text);

                            if (!String.IsNullOrEmpty(name.Lang))
                            {
                                enName.Add(new XAttribute(XNamespace.Xml + "lang", name.Lang));
                            }

                            keyfamily.Add(enName);
                        }
                    }
                }
                else
                {
                    throw new Exception("At least one name should be added to the KeyFamily.");
                }

                if (kf.Description.Count > 0)
                {
                    foreach (SDMX_Common.TextType description in kf.Description)
                    {
                        if (description.Text != null)
                        {
                            XElement enDescription = new XElement(_nsStructur + "Name", description.Text);

                            if (description.Lang != null)
                            {
                                enDescription.Add(new XAttribute(XNamespace.Xml + "lang", description.Lang));
                            }

                            keyfamily.Add(enDescription);
                        }
                    }
                }

                keyfamily.Add(getComponents(kf.Component));

                if (kf.Annotations != null)
                {
                    XElement annotations = ElementBuilder.GetAnnotations(kf.Annotations, _nsStructur);

                    keyfamily.Add(annotations);
                }

                keyfamilies.Add(keyfamily);
            }

            return keyfamilies;

        }

        private XElement getComponents(SDMX_Structure.ComponentsType comp)
        {
            XElement component = new XElement(_nsStructur + "Components");

            foreach (SDMX_Structure.DimensionType d in comp.Dimensions)
            {
                component.Add(getDimension(d));
            }

            if(comp.Timedimension != null)
            {
                component.Add(GetTimeDimension(comp.Timedimension));
            }

            foreach (SDMX_Structure.GroupType g in comp.Group)
            {
                component.Add(GetGroup(g));
            }

            if (comp.Primarymeasure != null)
            {
                component.Add(getPrimaryMeasure(comp.Primarymeasure));
            }

            foreach(SDMX_Structure.CrossSectionalMeasure measure in comp.Crosssectionalmeasure)
            {
                component.Add(GetCrossSectionalMeasureType(measure));
            }

            foreach (SDMX_ML.Framework.Structure.AttributeType a in comp.Attribute)
            {
                component.Add(getAttribute(a));
            }
            

            return component;
        }

        private XElement getDimension(SDMX_Structure.DimensionType d)
        {
            XElement dimension = new XElement(_nsStructur + "Dimension");
            
            if(d.Conceptref != null)
            {
                dimension.Add(new XAttribute("conceptRef", d.Conceptref.Value));
            }

            if(d.ConceptVersion != null)
            {
                dimension.Add(new XAttribute("conceptVersion", d.ConceptVersion));
            }

            if (d.ConceptAgency != null)
            {
                dimension.Add(new XAttribute("conceptAgency", d.ConceptAgency.Value));
            }

            if (d.ConceptSchemeRef != null)
            {
                dimension.Add(new XAttribute("conceptSchemeRef", d.ConceptSchemeRef.Value));
            }

            if (d.ConceptSchemeAgency != null)
            {
                dimension.Add(new XAttribute("conceptSchemeAgency", d.ConceptSchemeAgency.Value));
            }

            if(d.Codelist != null)
            {
                dimension.Add(new XAttribute("codelist", d.Codelist.Value));
            }

            if (d.CodeListVersion != null)
            {
                dimension.Add(new XAttribute("codelistVersion", d.CodeListVersion));
            }

            if (d.CodeListAgency != null)
            {
                dimension.Add(new XAttribute("codelistAgency", d.CodeListAgency.Value));
            }

            if (d.IsMeasureDimension != null)
            {
                dimension.Add(new XAttribute("isMeasureDimension", d.IsMeasureDimension.ToString().ToLower()));
            }

            if(d.IsFrequencyDimension != null)
            {
                dimension.Add(new XAttribute("isFrequencyDimension", d.IsFrequencyDimension.ToString().ToLower()));
            }

            if (d.IsEntityDimension != null)
            {
                dimension.Add(new XAttribute("IsEntityDimension", d.IsEntityDimension.ToString().ToLower()));
            }

            if (d.IsCountDimension != null)
            {
                dimension.Add(new XAttribute("isCountDimension", d.IsCountDimension.ToString().ToLower()));
            }

            if (d.IsNonObservationTimeDimension != null)
            {
                dimension.Add(new XAttribute("isNonObservationTimeDimension", d.IsNonObservationTimeDimension.ToString().ToLower()));
            }

            if (d.IsIdentityDimension != null)
            {
                dimension.Add(new XAttribute("isIdentityDimension", d.IsIdentityDimension.ToString().ToLower()));
            }

            if (d.CrossSectionalAttachDataSet != null)
            {
                dimension.Add(new XAttribute("crossSectionalAttachDataSet", d.CrossSectionalAttachDataSet.ToString().ToLower()));
            }

            if (d.CrossSectionalAttachGroup != null)
            {
                dimension.Add(new XAttribute("crossSectionalAttachGroup", d.CrossSectionalAttachGroup.ToString().ToLower()));
            }

            if (d.CrossSectionalAttachSection != null)
            {
                dimension.Add(new XAttribute("crossSectionalAttachSection", d.CrossSectionalAttachSection.ToString().ToLower()));
            }

            if (d.CrossSectionalAttachObservation != null)
            {
                dimension.Add(new XAttribute("crossSectionalAttachObservation", d.CrossSectionalAttachObservation.ToString().ToLower()));
            }

            if (d.TextFormat != null)
            {
                foreach (SDMX_Structure.TextFormatType textFormatType in d.TextFormat)
                {
                    dimension.Add(ElementBuilder.GetTextFormatType(textFormatType));
                }
            }

            if (d.Annotations != null)
            {
                XElement annotations = ElementBuilder.GetAnnotations(d.Annotations, Namespaces.GetNS("structure"));

                dimension.Add(annotations);
            }

            return dimension;
          
        }

        private XElement GetTimeDimension(SDMX_Structure.TimeDimensionType timeDimensionType)
        {
            XElement timeDimension = new XElement(_nsStructur + "TimeDimension");

            if (timeDimensionType.ConceptRef != null)
            {
                timeDimension.Add(new XAttribute("conceptRef", timeDimensionType.ConceptRef.Value));
            }

            if (timeDimensionType.ConceptVersion != null)
            {
                timeDimension.Add(new XAttribute("conceptVersion", timeDimensionType.ConceptVersion));
            }

            if (timeDimensionType.ConceptAgency != null)
            {
                timeDimension.Add(new XAttribute("conceptAgency", timeDimensionType.ConceptAgency.Value));
            }

            if (timeDimensionType.ConceptSchemeRef != null)
            {
                timeDimension.Add(new XAttribute("conceptSchemaRef", timeDimensionType.ConceptSchemeRef.Value));
            }

            if (timeDimensionType.ConceptSchemeAgency != null)
            {
                timeDimension.Add(new XAttribute("conceptSchemaAgency", timeDimensionType.ConceptSchemeAgency.Value));
            }

            if (timeDimensionType.Codelist != null)
            {
                timeDimension.Add(new XAttribute("codelist", timeDimensionType.Codelist.Value));
            }

            if (timeDimensionType.CodeListVersion != null)
            {
                timeDimension.Add(new XAttribute("codelistVersion", timeDimensionType.CodeListVersion));
            }

            if (timeDimensionType.CodeListAgency != null)
            {
                timeDimension.Add(new XAttribute("codelistAgency", timeDimensionType.CodeListAgency.Value));
            }

            if (timeDimensionType.CrossSectionalAttachDataSet != null)
            {
                timeDimension.Add(new XAttribute("crossSectionalAttachDataSet", timeDimensionType.CrossSectionalAttachDataSet.ToString().ToLower()));
            }

            if (timeDimensionType.CrossSectionalAttachGroup != null)
            {
                timeDimension.Add(new XAttribute("crossSectionalAttachGroup", timeDimensionType.CrossSectionalAttachGroup.ToString().ToLower()));
            }

            if (timeDimensionType.CrossSectionalAttachSection != null)
            {
                timeDimension.Add(new XAttribute("crossSectionalAttachSection", timeDimensionType.CrossSectionalAttachSection.ToString().ToLower()));
            }

            if (timeDimensionType.CrossSectionalAttachObservation != null)
            {
                timeDimension.Add(new XAttribute("crossSectionalAttachObservation", timeDimensionType.CrossSectionalAttachObservation.ToString().ToLower()));
            }

            if (timeDimensionType.TextFormat != null)
            {
                foreach (SDMX_Structure.TextFormatType textFormatType in timeDimensionType.TextFormat)
                {
                    timeDimension.Add(ElementBuilder.GetTextFormatType(textFormatType));
                }
            }

            if (timeDimensionType.Annotations != null)
            {
                XElement annotations = ElementBuilder.GetAnnotations(timeDimensionType.Annotations, Namespaces.GetNS("structure"));

                timeDimension.Add(annotations);
            }

            return timeDimension;

        }

        private XElement GetGroup(SDMX_Structure.GroupType groupType)
        {
            XElement group = new XElement(_nsStructur + "Group");

            if (groupType.Id != null)
            {
                if (groupType.Id.Value != null)
                {
                    group.Add(new XAttribute("id", groupType.Id.Value));
                }
            }

            //Choice
            if (groupType.DimensionRef.Count > 0)
            {
                foreach(SDMX_Common.IDType idType in groupType.DimensionRef)
                {
                    group.Add(new XElement(_nsStructur + "DimensionRef", idType.Value));
                }
            }
            else if (groupType.AttachmentConstraintRef != null)
            {
                group.Add(new XElement(_nsStructur + "AttachmentConstraintRef", groupType.AttachmentConstraintRef.Value));
            }

            if (groupType.Description.Count > 0)
            {
                foreach (SDMX_Common.TextType textType in groupType.Description)
                {
                    group.Add(ElementBuilder.GetTextType(textType, "Description", Namespaces.GetNS("structure")));
                }
            }

            if (groupType.Annotations != null)
            {
                XElement annotations = ElementBuilder.GetAnnotations(groupType.Annotations, Namespaces.GetNS("structure"));

                 group.Add(annotations);
            }

            return group;

        }

        private XElement GetCrossSectionalMeasureType(SDMX_Structure.CrossSectionalMeasure cm)
        {
            XElement measure = new XElement(_nsStructur + "CrossSectionalMeasure");

            if (cm.ConceptRef != null)
            {
                measure.Add(new XAttribute("conceptRef", cm.ConceptRef.Value));
            }

            if (cm.ConceptVersion != null)
            {
                measure.Add(new XAttribute("conceptVersion", cm.ConceptVersion));
            }

            if (cm.ConceptAgency != null)
            {
                measure.Add(new XAttribute("conceptAgency", cm.ConceptAgency.Value));
            }

            if (cm.ConceptSchemaRef != null)
            {
                measure.Add(new XAttribute("conceptSchemaRef", cm.ConceptSchemaRef.Value));
            }

            if (cm.ConceptSchemaAgency != null)
            {
                measure.Add(new XAttribute("conceptSchemaAgency", cm.ConceptSchemaAgency.Value));
            }

            if (cm.Codelist != null)
            {
                measure.Add(new XAttribute("codelist", cm.Codelist.Value));
            }

            if (cm.CodelistVersion != null)
            {
                measure.Add(new XAttribute("codelistVersion", cm.CodelistVersion));
            }

            if (cm.CodelistAgency != null)
            {
                measure.Add(new XAttribute("codelistAgency", cm.CodelistAgency.Value));
            }

            if (cm.MeasureDimension != null)
            {
                measure.Add(new XAttribute("measureDimension", cm.MeasureDimension.Value));
            }

            if (cm.Code != null)
            {
                measure.Add(new XAttribute("code", cm.Code.Value));
            }

            if (cm.TextFormat != null)
            {
                foreach (SDMX_Structure.TextFormatType textFormatType in cm.TextFormat)
                {
                    measure.Add(ElementBuilder.GetTextFormatType(textFormatType));
                }
            }

            if (cm.Annotations != null)
            {
                XElement annotations = ElementBuilder.GetAnnotations(cm.Annotations, _nsStructur);

                 measure.Add(annotations);
            }

            return measure;
        }

        private XElement getPrimaryMeasure(SDMX_Structure.PrimaryMeasureType pm)
        {
            XElement primary = new XElement(_nsStructur + "PrimaryMeasure");

            if (pm.ConceptRef != null)
            {
                primary.Add(new XAttribute("conceptRef", pm.ConceptRef.Value));
            }

            if (pm.ConceptVersion != null)
            {
                primary.Add(new XAttribute("conceptVersion", pm.ConceptVersion));
            }

            if (pm.ConceptAgency != null)
            {
                primary.Add(new XAttribute("conceptAgency", pm.ConceptAgency.Value));
            }

            if (pm.ConceptSchemaRef != null)
            {
                primary.Add(new XAttribute("conceptSchemeRef", pm.ConceptSchemaRef.Value));
            }

            if (pm.ConceptSchemaAgency != null)
            {
                primary.Add(new XAttribute("conceptSchemeAgency", pm.ConceptSchemaAgency.Value));
            }

            if (pm.Codelist != null)
            {
                primary.Add(new XAttribute("codelist", pm.Codelist.Value));
            }

            if (pm.CodelistVersion != null)
            {
                primary.Add(new XAttribute("codelistVersion", pm.CodelistVersion));
            }

            if (pm.CodelistAgency != null)
            {
                primary.Add(new XAttribute("codelistAgency", pm.CodelistAgency.Value));
            }

            if (pm.TextFormat != null)
            {
                foreach (SDMX_Structure.TextFormatType textFormatType in pm.TextFormat)
                {
                    primary.Add(ElementBuilder.GetTextFormatType(textFormatType));
                }
            }

            if (pm.Annotations != null)
            {
                XElement annotations = ElementBuilder.GetAnnotations(pm.Annotations, _nsStructur);

                primary.Add(annotations);
            }

            return primary;
        }

        private XElement getAttribute(SDMX_ML.Framework.Structure.AttributeType a)
        {
            XElement attribute = new XElement(_nsStructur + "Attribute");

            if (a.ConceptRef != null)
            {
                attribute.Add(new XAttribute("conceptRef", a.ConceptRef.Value));
            }

            if (a.ConceptVersion != null)
            {
                attribute.Add(new XAttribute("conceptVersion", a.ConceptVersion));
            }

            if (a.ConceptAgency != null)
            {
                attribute.Add(new XAttribute("conceptAgency", a.ConceptAgency.Value));
            }

            if (a.ConceptSchemeRef != null)
            {
                attribute.Add(new XAttribute("conceptSchemeRef", a.ConceptSchemeRef.Value));
            }

            if (a.ConceptSchemeAgency != null)
            {
                attribute.Add(new XAttribute("conceptSchemeAgency", a.ConceptSchemeAgency.Value));
            }

            if (a.Codelist != null)
            {
                attribute.Add(new XAttribute("codelist", a.Codelist.Value));
            }

            if (a.CodelistVersion != null)
            {
                attribute.Add(new XAttribute("codelistVersion", a.CodelistVersion));
            }

            if (a.CodelistAgency != null)
            {
                attribute.Add(new XAttribute("codelistAgency", a.CodelistAgency.Value));
            }

            if (a.AttachmentLevel != null)
            {
                attribute.Add(new XAttribute("attachmentLevel", a.AttachmentLevel));
            }

            if (a.AssignmentStatus != null)
            {
                attribute.Add(new XAttribute("assignmentStatus", a.AssignmentStatus));
            }

            if (a.IsTimeFormat != null)
            {
                attribute.Add(new XAttribute("isTimeFormat", a.IsTimeFormat.ToString().ToLower()));
            }

            if (a.CrossSectionalAttachDataset != null)
            {
                attribute.Add(new XAttribute("crossSectionalAttachDataSet", a.CrossSectionalAttachDataset.ToString().ToLower()));
            }

            if (a.CrossSectionalAttachGroup != null)
            {
                attribute.Add(new XAttribute("crossSectionalAttachGroup", a.CrossSectionalAttachGroup.ToString().ToLower()));
            }

            if (a.CrossSectionalAttachSection != null)
            {
                attribute.Add(new XAttribute("crossSectionalAttachSection", a.CrossSectionalAttachSection.ToString().ToLower()));
            }

            if (a.CrossSectionalAttachObservation != null)
            {
                attribute.Add(new XAttribute("crossSectionalAttachObservation", a.CrossSectionalAttachObservation.ToString().ToLower()));
            }

            if (a.IsEntityAttribute != null)
            {
                attribute.Add(new XAttribute("isEntityAttribute", a.IsEntityAttribute.ToString().ToLower()));
            }

            if (a.IsNonObservationalTimeAttribute != null)
            {
                attribute.Add(new XAttribute("isNonObservationTimeAttribute", a.IsNonObservationalTimeAttribute.ToString().ToLower()));
            }

            if (a.IsCountAttribute != null)
            {
                attribute.Add(new XAttribute("isCountAttribute", a.IsCountAttribute.ToString().ToLower()));
            }

            if (a.IsFrequencyAttribute != null)
            {
                attribute.Add(new XAttribute("isFrequencyAttribute", a.IsFrequencyAttribute.ToString().ToLower()));
            }

            if (a.IsIdentityAttribute != null)
            {
                attribute.Add(new XAttribute("isIdentityAttribute", a.IsIdentityAttribute.ToString().ToLower()));
            }

            if (a.TextFormat != null)
            {
                foreach (SDMX_Structure.TextFormatType textFormatType in a.TextFormat)
                {
                    attribute.Add(ElementBuilder.GetTextFormatType(textFormatType));
                }
            }

            if (a.Annotations != null)
            {
                XElement annotations = ElementBuilder.GetAnnotations(a.Annotations, _nsStructur);

                    attribute.Add(annotations);
            }

            return attribute;
          
        }

        #endregion

        #region Public methods

        /// <summary>
        /// Writes the content to a xml file.
        /// </summary>
        /// <param name="file">Path and name of file.</param>
        /// <param name="content">Content of a SDMX_ML file.</param>
        public void Write(string file, string content)
        {
            try
            {
                using (TextWriter writer = new StreamWriter(file))
                {
                    try
                    {
                        writer.Write(content);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("Unexpected error when wrting to file. " + ex.Message);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Unexpected error when creating file. " + ex.Message);
            }
        }
        /// <summary>
        /// Load SDMX_ML Structure file into Structure object.
        /// </summary>
        /// <param name="file">Path and name of file.</param>
        /// <returns></returns>
        public static Structure Load(string file)
        {
            Structure structure = null;

            if (File.Exists(file))
            {
                using (TextReader reader = new StreamReader(file))
                {
                    string fileContent = reader.ReadToEnd();

                    try
                    {
                        structure = new Structure(fileContent);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("Unexpected error when creating Structure object. " + ex.Message);
                    }
                }

                return structure;
            }
            else
            {
                throw new FileNotFoundException("File not found when trying to create Structure object.", file);
            }
        }

        #endregion
    }
}
